original_code:
static void ffs_format(int fd, off_t bytes, int blksize)
{
 const ffs_superblock sb = {
  .magic = "FAILFS",
  .block_type = FFS_BT_SUPER,
  .block_size = blksize,
  .num_blocks = bytes / blksize,
  .root_block = 3,
  .free_block = 4
 };
 if( lseek(fd, blksize * 2, 0) == (off_t)-1 )
  err(1, "lseek");
 if( write(fd, &sb, sizeof(sb)) != sizeof(sb) )
  err(1, "write(superblock)");
    const ffs_file_block root = {
        .magic = "FAILFS",
        .block_type = FFS_BT_FILE,
        .size = 0,
        .type = FFS_FT_DIR,
        .flags = 0,
        .owner = 0,
        .group = 0,
        .perms = 0755,
        .major = 0,
        .minor = 0,
        .atime = time(0),
        .mtime = time(0),
        .ctime = time(0),
        .name = "/",
        .child = 0,
        .next = 0,
        .parent = 0,
    };
    if( lseek(fd, blksize * sb.root_block, 0) == (off_t)-1 ) {
        err(1, "lseek"); }
    if( write(fd, &root, sizeof(root)) != sizeof(root) ) {
  err(1, "write(root)"); }
 const int fb_len = (blksize - sizeof(ffs_free_block));
 const int num_fb = sb.num_blocks / (fb_len * 64);
 printf("mkfs.failfs: %u free blocks required for %u total blocks of %u bytes\n",
   num_fb,
   sb.num_blocks,
   blksize
   );
 ffs_free_block **fb;
 if( (fb = calloc(num_fb, sizeof(ffs_free_block *))) == ((void *)0) )
  err(1, "calloc");
 for( int i = 0; i < num_fb; i++ )
 {
  if ( (fb[i] = calloc(1, sizeof(ffs_free_block) + fb_len)) == ((void *)0) )
   err(1, "malloc");
  *fb[i] = (ffs_free_block){
   .magic = "FAILFS",
   .block_type = FFS_BT_FREE,
   .len = fb_len,
   .next = (i + 1 == num_fb) ? 0 : sb.free_block + i + 1,
   .prev = (i == 0) ? 0 : sb.free_block + i - 1,
   .flags = 0
  };
 }
 fb[0]->data[0] |= 0x1|0x2|0x4|0x8;
 for( int i = 0; i < num_fb; i++ )
  fb[0]->data[0] |= (1 << (i + 4));
 for( int i = 0; i < num_fb; i++ )
 {
  printf("mkfs.failfs: writing sector %d\n", (sb.free_block + i));
  if( lseek(fd, (sb.free_block + i) * blksize, 0) == -1 )
   err(1, "lseek");
  if( write(fd, fb[i], sizeof(ffs_free_block) + fb_len) != (int)(sizeof(ffs_free_block) + fb_len) )
   err(1, "write(freeblock:%d)", i);
 }
 for( int i = 0; i < num_fb; i++ )
  if(fb[i])
   free(fb[i]);
 free(fb);
}

canonical_original_code:
static void ffs_format(int fd, long bytes, int blksize)
{
 struct _ffs_superblock sb = {
  .magic = "FAILFS",
  .block_type = FFS_BT_SUPER,
  .block_size = blksize,
  .num_blocks = bytes / blksize,
  .root_block = 3,
  .free_block = 4
 };
 if( lseek(fd, blksize * 2, 0) == (off_t)-1 )
  err(1, "lseek");
 if( write(fd, &sb, sizeof(sb)) != sizeof(sb) )
  err(1, "write(superblock)");
    struct _ffs_file_block root = {
        .magic = "FAILFS",
        .block_type = FFS_BT_FILE,
        .size = 0,
        .type = FFS_FT_DIR,
        .flags = 0,
        .owner = 0,
        .group = 0,
        .perms = 0755,
        .major = 0,
        .minor = 0,
        .atime = time(0),
        .mtime = time(0),
        .ctime = time(0),
        .name = "/",
        .child = 0,
        .next = 0,
        .parent = 0,
    };
    if( lseek(fd, blksize * sb.root_block, 0) == (off_t)-1 ) {
        err(1, "lseek"); }
    if( write(fd, &root, sizeof(root)) != sizeof(root) ) {
  err(1, "write(root)"); }
 int fb_len = (blksize - sizeof(ffs_free_block));
 int num_fb = sb.num_blocks / (fb_len * 64);
 printf("mkfs.failfs: %u free blocks required for %u total blocks of %u bytes\n",
   num_fb,
   sb.num_blocks,
   blksize
   );
 struct _ffs_free_block **fb;
 if( (fb = calloc(num_fb, sizeof(struct _ffs_free_block *))) == ((void *)0) )
  err(1, "calloc");
 for( int i = 0; i < num_fb; i++ )
 {
  if ( (fb[i] = calloc(1, sizeof(ffs_free_block) + fb_len)) == ((void *)0) )
   err(1, "malloc");
  *fb[i] = (struct _ffs_free_block){
   .magic = "FAILFS",
   .block_type = FFS_BT_FREE,
   .len = fb_len,
   .next = (i + 1 == num_fb) ? 0 : sb.free_block + i + 1,
   .prev = (i == 0) ? 0 : sb.free_block + i - 1,
   .flags = 0
  };
 }
 fb[0]->data[0] |= 0x1|0x2|0x4|0x8;
 for( int i = 0; i < num_fb; i++ )
  fb[0]->data[0] |= (1 << (i + 4));
 for( int i = 0; i < num_fb; i++ )
 {
  printf("mkfs.failfs: writing sector %d\n", (sb.free_block + i));
  if( lseek(fd, (sb.free_block + i) * blksize, 0) == -1 )
   err(1, "lseek");
  if( write(fd, fb[i], sizeof(ffs_free_block) + fb_len) != (int)(sizeof(ffs_free_block) + fb_len) )
   err(1, "write(freeblock:%d)", i);
 }
 for( int i = 0; i < num_fb; i++ )
  if(fb[i])
   free(fb[i]);
 free(fb);
}

variable_types: bytes long

variable_types: blksize int

variable_types: struct _ffs_superblock { unsigned char magic[6]; unsigned short block_type; unsigned short block_size; unsigned int num_blocks; unsigned short root_block; unsigned short free_block; }

variable_types: struct _ffs_file_block { unsigned char magic[6]; unsigned short block_type; unsigned short type; char name[128]; unsigned int child; unsigned int parent; unsigned int next; unsigned int target; unsigned long size; unsigned long flags; unsigned int owner; unsigned int group; unsigned long perms; unsigned short major; unsigned short minor; unsigned long nlink; unsigned long atime; unsigned int data; unsigned long res[4]; }

variable_types: struct _ffs_free_block { unsigned char magic[6]; unsigned short block_type; unsigned short len; unsigned short pad0; unsigned int next; unsigned int prev; unsigned long flags; unsigned long res[4]; unsigned long data[]; } **


insw

repo: juur/FailOS

decompiled_code:
void __fastcall insw(unsigned __int16 a1, unsigned __int16 *a2, unsigned int a3)
{
__inwordstring(a1, a2, a3);
}

canonical_decompiled_code:
void __fastcall func0(unsigned __int16 a1, unsigned __int16 *a2, unsigned int a3)
{
__inwordstring(a1, a2, a3);
}

original_code:
__attribute__((unused)) static inline void insw (unsigned short _port, void *addr, uint64_t _cnt)
{
 __asm__ volatile (
   "cld ; rep ; insw"
   : "=D" (addr), "=c" (_cnt)
   : "d" (_port), "0" (addr), "1" (_cnt)
   : "memory"
   );
}

canonical_original_code:
static inline void insw(unsigned short _port, void *addr, unsigned long _cnt)
{
 __asm__ volatile (
   "cld ; rep ; insw"
   : "=D" (addr), "=c" (_cnt)
   : "d" (_port), "0" (addr), "1" (_cnt)
   : "memory"
   );
}

variable_types:
addr
void *

return_type: void


outw

decompiled_code:
void __fastcall outw(unsigned __int16 a1, unsigned __int16 *a2, unsigned int a3)
{
__outwordstring(a1, a2, a3);
}

canonical_decompiled_code:
void __fastcall func1(unsigned __int16 a1, unsigned __int16 *a2, unsigned int a3)
{
__outwordstring(a1, a2, a3);
}

original_code:
__attribute__((unused)) static inline void outw (unsigned short _port, const void *addr, uint64_t _cnt)
{
 __asm__ volatile (
   "cld ; rep ; outsw"
   : "=S" (addr), "=c" (_cnt)
   : "d" (_port), "0" (addr), "1" (_cnt)
   : "memory"
   );
}

canonical_original_code:
static inline void outw(unsigned short _port, void *addr, unsigned long _cnt)
{
 __asm__ volatile (
   "cld ; rep ; outsw"
   : "=S" (addr), "=c" (_cnt)
   : "d" (_port), "0" (addr), "1" (_cnt)
   : "memory"
   );
}


decompiled_code:
__int64 __fastcall ide_wait(__int16 a1, unsigned __int8 a2, char *a3)
{
__int64 v4; // rbx
char v6; // [rsp+Fh] [rbp-29h]

v4 = 10000LL;
while ( 1 )
{
v6 = inportb((unsigned __int16)(a1 + 7));
*a3 = v6;
if ( v6 >= 0 )
{
if ( (v6 & 1) != 0 )
return 0LL;
if ( (a2 & (unsigned __int8)v6) != 0 )
break;
}
_mm_pause();
if ( !--v4 )
return 0LL;
}
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int16 a1, unsigned __int8 a2, char *a3)
{
__int64 v4; // rbx
char v6; // [rsp+Fh] [rbp-29h]

v4 = 10000LL;
while ( 1 )
{
v6 = inportb((unsigned __int16)(a1 + 7));
*a3 = v6;
if ( v6 >= 0 )
{
if ( (v6 & 1) != 0 )
return 0LL;
if ( (a2 & (unsigned __int8)v6) != 0 )
break;
}
_mm_pause();
if ( !--v4 )
return 0LL;
}
return 1LL;
}

original_code:
__attribute__((nonnull)) static bool ide_wait(uint16_t cmd, uint8_t mask, uint8_t *code)
{
 uint64_t cnt;
 volatile uint8_t t8;
 cnt = 10000;
 while(cnt--)
 {
  *code = t8 = inportb(cmd + 0x07);
  __asm__ volatile("nop":::"memory");
  if(t8 & 0x80) __asm__ volatile("pause");
  else if(t8 & 0x01) return 0;
  else if(t8 & mask) return 1;
  else __asm__ volatile("pause");
 }
 return 0;
}

canonical_original_code:
static _Bool ide_wait(unsigned short cmd, unsigned char mask, unsigned char *code)
{
 unsigned long cnt;
 unsigned char t8;
 cnt = 10000;
 while(cnt--)
 {
  *code = t8 = inportb(cmd + 0x07);
  __asm__ volatile("nop":::"memory");
  if(t8 & 0x80) __asm__ volatile("pause");
  else if(t8 & 0x01) return 0;
  else if(t8 & mask) return 1;
  else __asm__ volatile("pause");
 }
 return 0;
}

variable_types:
cmd
unsigned short

variable_types:
mask
unsigned char

variable_types:
code
unsigned char *

variable_types:
cnt
unsigned long


decompiled_code:
__int64 __fastcall init_ide(__int64 a1)
{
unsigned int v1; // ebp
unsigned __int16 v3; // r12
unsigned __int16 v4; // ax

v1 = *(_DWORD *)(a1 + 124);
printf("init_ide: called on pci_dev:0x%p IO:%x\n", (const void *)a1, v1);
v3 = pci_read_conf16(*(unsigned __int8 *)(a1 + 8), *(unsigned __int8 *)(a1 + 9), *(unsigned __int8 *)(a1 + 10), 4LL);
pci_write_conf16(
*(unsigned __int8 *)(a1 + 8),
*(unsigned __int8 *)(a1 + 9),
*(unsigned __int8 *)(a1 + 10),
4LL,
v3 | 1u);
if ( (v3 & 4) == 0 )
{
pci_write_conf16(
*(unsigned __int8 *)(a1 + 8),
*(unsigned __int8 *)(a1 + 9),
*(unsigned __int8 *)(a1 + 10),
4LL,
v3 | 4u);
printf("init_ide: enabling PCI master bit\n");
}
v4 = pci_read_conf16(*(unsigned __int8 *)(a1 + 8), *(unsigned __int8 *)(a1 + 9), *(unsigned __int8 *)(a1 + 10), 72LL);
pci_write_conf16(
*(unsigned __int8 *)(a1 + 8),
*(unsigned __int8 *)(a1 + 9),
*(unsigned __int8 *)(a1 + 10),
72LL,
v4 | 0xFu);
outportw((unsigned __int16)(v1 + 64), 17LL);
init_ide_port(0x1F0u, 0);
return init_ide_port(0x170u, 1u);
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1)
{
unsigned int v1; // ebp
unsigned __int16 v3; // r12
unsigned __int16 v4; // ax

v1 = *(_DWORD *)(a1 + 124);
printf("init_ide: called on pci_dev:0x%p IO:%x\n", (const void *)a1, v1);
v3 = pci_read_conf16(*(unsigned __int8 *)(a1 + 8), *(unsigned __int8 *)(a1 + 9), *(unsigned __int8 *)(a1 + 10), 4LL);
pci_write_conf16(
*(unsigned __int8 *)(a1 + 8),
*(unsigned __int8 *)(a1 + 9),
*(unsigned __int8 *)(a1 + 10),
4LL,
v3 | 1u);
if ( (v3 & 4) == 0 )
{
pci_write_conf16(
*(unsigned __int8 *)(a1 + 8),
*(unsigned __int8 *)(a1 + 9),
*(unsigned __int8 *)(a1 + 10),
4LL,
v3 | 4u);
printf("init_ide: enabling PCI master bit\n");
}
v4 = pci_read_conf16(*(unsigned __int8 *)(a1 + 8), *(unsigned __int8 *)(a1 + 9), *(unsigned __int8 *)(a1 + 10), 72LL);
pci_write_conf16(
*(unsigned __int8 *)(a1 + 8),
*(unsigned __int8 *)(a1 + 9),
*(unsigned __int8 *)(a1 + 10),
72LL,
v4 | 0xFu);
outportw((unsigned __int16)(v1 + 64), 17LL);
func7(0x1F0u, 0);
return func7(0x170u, 1u);
}

original_code:
__attribute__((nonnull)) void init_ide(struct pci_dev *const d)
{
 uint32_t io = d->bars[4].addr;
 uint16_t tmp,t16;
 printf("init_ide: called on pci_dev:0x%p IO:%x\n", (void *)d, io);
 tmp = pci_read_conf16(d->bus, d->dev, d->func, 0x4);
 pci_write_conf16(d->bus, d->dev, d->func, 0x4,
   tmp|0x1);
 if(!(tmp & 0x04)) {
  pci_write_conf16(d->bus, d->dev, d->func, 0x4,
    tmp|0x04);
  printf("init_ide: enabling PCI master bit\n");
 }
 t16 = pci_read_conf16(d->bus, d->dev, d->func, 0x48);
 pci_write_conf16(d->bus, d->dev, d->func, 0x48,
   t16|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0));
 outportw(io + 0x40, (1 << 0)|(1 << 4));
 init_ide_port(0x01f0, 0);
 init_ide_port(0x0170, 1);
}

canonical_original_code:
void init_ide(struct pci_dev *d)
{
 unsigned int io = d->bars[4].addr;
 unsigned short tmp; unsigned short t16;
 printf("init_ide: called on pci_dev:0x%p IO:%x\n", (void *)d, io);
 tmp = pci_read_conf16(d->bus, d->dev, d->func, 0x4);
 pci_write_conf16(d->bus, d->dev, d->func, 0x4,
   tmp|0x1);
 if(!(tmp & 0x04)) {
  pci_write_conf16(d->bus, d->dev, d->func, 0x4,
    tmp|0x04);
  printf("init_ide: enabling PCI master bit\n");
 }
 t16 = pci_read_conf16(d->bus, d->dev, d->func, 0x48);
 pci_write_conf16(d->bus, d->dev, d->func, 0x48,
   t16|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0));
 outportw(io + 0x40, (1 << 0)|(1 << 4));
 init_ide_port(0x01f0, 0);
 init_ide_port(0x0170, 1);
}

variable_types: struct pci_dev { struct pci_dev *next; unsigned char bus; struct pcicfg { unsigned short vendor_id; unsigned short device_id; unsigned short cmd_reg; unsigned short status_reg; unsigned int rev; unsigned char progif; unsigned char subclass; unsigned char class_code; unsigned char pad0; unsigned char pad1; unsigned char header_type; unsigned char pad2; unsigned int bar[6]; unsigned int pad3; unsigned short sub_vendor_id; unsigned short sub_id; unsigned int pad4; unsigned int pad5; unsigned int res0; unsigned int res1; unsigned char int_line; unsigned char int_pin; unsigned char pad6; unsigned char pad7; } cfg; struct pcibar { unsigned int addr; unsigned int len; union { struct { unsigned char pad; } io; struct { unsigned char bits; unsigned char prefs; } mem; } un; _Bool mem; } bars[6]; } *

variable_types:
io
unsigned int

variable_types:
tmp
unsigned short

user_defined_types: struct pci_dev { struct pci_dev *next; unsigned char bus; struct pcicfg cfg; struct pcibar bars[6]; }


checksum

decompiled_code:
__int64 __fastcall checksum(unsigned __int16 *a1, unsigned int a2)
{
unsigned __int16 *v2; // rcx
unsigned int v3; // eax
int v4; // edx

if ( a2 <= 1 )
{
v2 = a1;
v3 = 0;
}
else
{
v2 = &a1[((a2 - 2) >> 1) + 1];
v3 = 0;
do
{
v4 = *a1++;
v3 += v4;
}
while ( v2 != a1 );
a2 &= 1u;
}
if ( a2 )
v3 += *(unsigned __int8 *)v2;
return ~((unsigned __int16)v3 + HIWORD(v3) + ((unsigned int)((unsigned __int16)v3 + HIWORD(v3)) >> 16));
}

canonical_decompiled_code:
__int64 __fastcall func9(unsigned __int16 *a1, unsigned int a2)
{
unsigned __int16 *v2; // rcx
unsigned int v3; // eax
int v4; // edx

if ( a2 <= 1 )
{
v2 = a1;
v3 = 0;
}
else
{
v2 = &a1[((a2 - 2) >> 1) + 1];
v3 = 0;
do
{
v4 = *a1++;
v3 += v4;
}
while ( v2 != a1 );
a2 &= 1u;
}
if ( a2 )
v3 += *(unsigned __int8 *)v2;
return ~((unsigned __int16)v3 + HIWORD(v3) + ((unsigned int)((unsigned __int16)v3 + HIWORD(v3)) >> 16));
}

original_code:
uint16_t checksum(uint16_t *data, uint32_t len)
{
 uint32_t sum;
 for(sum=0; len>1; len-=2)
  sum += *data++;
 if(len) sum += *(uint8_t*)data;
 sum = (sum >> 16) + (sum & 0xffff);
 sum += (sum >> 16);
 sum = ~sum;
 return (uint16_t)sum;
}

canonical_original_code:
unsigned short checksum(unsigned short *data, unsigned int len)
{
 unsigned int sum;
 for(sum=0; len>1; len-=2)
  sum += *data++;
 if(len) sum += *(unsigned char *)data;
 sum = (sum >> 16) + (sum & 0xffff);
 sum += (sum >> 16);
 sum = ~sum;
 return (unsigned short)sum;
}

variable_types:
data
unsigned short *

variable_types:
len
unsigned int

variable_types:
sum
unsigned int

return_type: unsigned short


repo: juxstapose/stykfighta

decompiled_code:
void log_init()
{
debug_level = 0;
}

canonical_decompiled_code:
void func0()
{
debug_level = 0;
}

original_code:
void log_init() {
    _debug_level = 0;
}

canonical_original_code:
void log_init() {
    _debug_level = 0;
}


decompiled_code:
void __fastcall log_set_debug_level(int a1)
{
debug_level = a1;
}

canonical_decompiled_code:
void __fastcall func1(int a1)
{
debug_level = a1;
}

original_code:
void log_set_debug_level(int debug_level) {
    _debug_level = debug_level;
}


decompiled_code:
int __fastcall log_file_open(const char *a1)
{
FILE *v1; // rax

v1 = fopen(a1, "w");
lfp = v1;
if ( !v1 )
LODWORD(v1) = fclose(0LL);
return (int)v1;
}

canonical_decompiled_code:
int __fastcall func2(const char *a1)
{
FILE *v1; // rax

v1 = fopen(a1, "w");
lfp = v1;
if ( !v1 )
LODWORD(v1) = fclose(0LL);
return (int)v1;
}

original_code:
void log_file_open(const char* filename) {
    _lfp = fopen(filename, "w");
    if(_lfp == ((void *)0)) {
        fclose(_lfp);
    }
}

canonical_original_code:
void log_file_open(char *filename) {
    _lfp = fopen(filename, "w");
    if(_lfp == ((void *)0)) {
        fclose(_lfp);
    }
}

variable_types:
filename
char *


decompiled_code:
int log_file_close()
{
return fclose(lfp);
}

canonical_decompiled_code:
int func3()
{
return fclose(lfp);
}

original_code:
void log_file_close() {
    fclose(_lfp);
}

canonical_original_code:
void log_file_close() {
    fclose(_lfp);
}


decompiled_code:
__int64 log_msg(int a1, const char *a2, ...)
{
unsigned int v2; // er12
__int64 v4; // rax
FILE *v5; // r13
size_t v6; // rax
gcc_va_list arg; // [rsp+8h] [rbp-40E0h] BYREF
char s[8]; // [rsp+20h] [rbp-40C8h] BYREF

v2 = 0;
if ( debug_level > a1 )
return v2;
va_start(arg, a2);
v4 = 0x203A4755424544LL;
if ( !a1 )
{
LABEL_9:
*(_QWORD *)s = v4;
v2 = vsnprintf(&s[7], 0x3FF9uLL, a2, arg) + 7;
goto LABEL_6;
}
if ( a1 != 1 )
{
if ( a1 != 2 )
goto LABEL_6;
v4 = 0x203A524F525245LL;
goto LABEL_9;
}
strcpy(s, "INFO: ");
v2 = vsnprintf(&s[6], 0x3FFAuLL, a2, arg) + 6;
LABEL_6:
printf("%s", s);
v5 = lfp;
if ( !lfp )
return v2;
v6 = strlen(s);
fwrite(s, 1uLL, v6, v5);
return v2;
}

canonical_decompiled_code:
__int64 func4(int a1, const char *a2, ...)
{
unsigned int v2; // er12
__int64 v4; // rax
FILE *v5; // r13
size_t v6; // rax
gcc_va_list arg; // [rsp+8h] [rbp-40E0h] BYREF
char s[8]; // [rsp+20h] [rbp-40C8h] BYREF

v2 = 0;
if ( debug_level > a1 )
return v2;
va_start(arg, a2);
v4 = 0x203A4755424544LL;
if ( !a1 )
{
LABEL_9:
*(_QWORD *)s = v4;
v2 = vsnprintf(&s[7], 0x3FF9uLL, a2, arg) + 7;
goto LABEL_6;
}
if ( a1 != 1 )
{
if ( a1 != 2 )
goto LABEL_6;
v4 = 0x203A524F525245LL;
goto LABEL_9;
}
strcpy(s, "INFO: ");
v2 = vsnprintf(&s[6], 0x3FFAuLL, a2, arg) + 6;
LABEL_6:
printf("%s", s);
v5 = lfp;
if ( !lfp )
return v2;
v6 = strlen(s);
fwrite(s, 1uLL, v6, v5);
return v2;
}

original_code:
int log_msg(int debug_level, const char* format, ...) {
    if(debug_level < _debug_level) {
        return 0;
    }
    char dest[1024 * 16];
    int count = 0;
    va_list arglist;
    __builtin_va_start(arglist,format);
    if(debug_level == 0) {
        strcpy(dest, "DEBUG: ");
        count = vsnprintf(&dest[7], 1024*16-7, format, arglist);
        count+=7;
    }
    if(debug_level == 1) {
        strcpy(dest, "INFO: ");
        count = vsnprintf(&dest[6], 1024*16-6, format, arglist);
        count+=6;
    }
    if(debug_level == 2) {
        strcpy(dest, "ERROR: ");
        count = vsnprintf(&dest[7], 1024*16-7, format, arglist);
        count+=7;
    }
    printf("%s", dest);
    if(_lfp != ((void *)0)) {
        fwrite(dest, 1, strlen(dest), _lfp);
    }
    __builtin_va_end(arglist);
    return count;
}

canonical_original_code:
int log_msg(int debug_level, char *format, ...) {
    if(debug_level < _debug_level) {
        return 0;
    }
    char dest[-1];
    int count = 0;
    __builtin_va_list arglist;
    __builtin_va_start(arglist,format);
    if(debug_level == 0) {
        strcpy(dest, "DEBUG: ");
        count = vsnprintf(&dest[7], 1024*16-7, format, arglist);
        count+=7;
    }
    if(debug_level == 1) {
        strcpy(dest, "INFO: ");
        count = vsnprintf(&dest[6], 1024*16-6, format, arglist);
        count+=6;
    }
    if(debug_level == 2) {
        strcpy(dest, "ERROR: ");
        count = vsnprintf(&dest[7], 1024*16-7, format, arglist);
        count+=7;
    }
    printf("%s", dest);
    if(_lfp != ((void *)0)) {
        fwrite(dest, 1, strlen(dest), _lfp);
    }
    __builtin_va_end(arglist);
    return count;
}

variable_types:
format
char *

variable_types:
dest
char [-1]

variable_types: count int

return_type: int


repo: jvirkki/dupd

decompiled_code:
int __fastcall operation_cache_delete(const char *a1)
{
int result; // eax
char v2[4104]; // [rsp+0h] [rbp-1008h] BYREF

result = unlink(a1);
if ( result )
{
snprintf(v2, 0x1000uLL, "unlink %s", a1);
perror(v2);
exit(1);
}
return result;
}

canonical_decompiled_code:
int __fastcall func0(const char *a1)
{
int result; // eax
char v2[4104]; // [rsp+0h] [rbp-1008h] BYREF

result = unlink(a1);
if ( result )
{
snprintf(v2, 0x1000uLL, "unlink %s", a1);
perror(v2);
exit(1);
}
return result;
}

original_code:
void operation_cache_delete(char * path)
{
  int rv = unlink(path);
  if (rv != 0) {
    char line[4096];
    snprintf(line, 4096, "unlink %s", path);
    perror(line);
    exit(1);
  }
}

canonical_original_code:
void operation_cache_delete(char *path)
{
  int rv = unlink(path);
  if (rv != 0) {
    char line[4096];
    snprintf(line, 4096, "unlink %s", path);
    perror(line);
    exit(1);
  }
}

variable_types:
path
char *

variable_types: rv int

variable_types:
line
char [4096]


decompiled_code:
__int64 operation_cache_ls()
{
open_cache_database();
cache_db_list_entries();
return close_cache_database();
}

canonical_decompiled_code:
__int64 func1()
{
open_cache_database();
cache_db_list_entries();
return close_cache_database();
}

original_code:
void operation_cache_ls(char * path)
{
  open_cache_database(path);
  cache_db_list_entries();
  close_cache_database();
}

canonical_original_code:
void operation_cache_ls(char *path)
{
  open_cache_database(path);
  cache_db_list_entries();
  close_cache_database();
}


decompiled_code:
void __fastcall handle_signal(int a1)
{
if ( a1 == 10 )
{
log_level = 9 * (log_level <= 9) + 1;
}
else if ( a1 == 12 )
{
dump_state = 1;
}
}

canonical_decompiled_code:
void __fastcall func0(int a1)
{
if ( a1 == 10 )
{
log_level = 9 * (log_level <= 9) + 1;
}
else if ( a1 == 12 )
{
dump_state = 1;
}
}

original_code:
void handle_signal(int sig)
{
  if (sig == 10) {
    if (log_level < 10) {
      log_level = 10;
    } else {
      log_level = 1;
    }
  } else if (sig == 12) {
    dump_state = 1;
  }
}

variable_types: sig int


decompiled_code:
void free_start_paths()
{
void **v0; // rbx

start_path_count = 0;
v0 = (void **)&start_path;
do
{
if ( *v0 )
{
free(*v0);
*v0 = 0LL;
}
++v0;
}
while ( v0 != (void **)(&start_path + 10) );
}

canonical_decompiled_code:
void func1()
{
void **v0; // rbx

start_path_count = 0;
v0 = (void **)&start_path;
do
{
if ( *v0 )
{
free(*v0);
*v0 = 0LL;
}
++v0;
}
while ( v0 != (void **)(&start_path + 10) );
}

original_code:
static void free_start_paths()
{
  start_path_count = 0;
  for (int n = 0; n < 10; n++) {
    if (start_path[n]) {
      free(start_path[n]);
      start_path[n] = ((void *)0);
    }
  }
}

variable_types: n int


decompiled_code:
int show_banner()
{
puts("dupd 2.0-dev Copyright 2012-2020 Jyri J. Virkki");
puts("This program comes with ABSOLUTELY NO WARRANTY.");
puts("This is free software, and you are welcome to redistribute it");
puts("under certain conditions. Run 'dupd license' for details.");
return putchar(10);
}

canonical_decompiled_code:
int func2()
{
puts("dupd 2.0-dev Copyright 2012-2020 Jyri J. Virkki");
puts("This program comes with ABSOLUTELY NO WARRANTY.");
puts("This is free software, and you are welcome to redistribute it");
puts("under certain conditions. Run 'dupd license' for details.");
return putchar(10);
}

original_code:
static void show_banner()
{
  printf("dupd " "2.0-dev" " Copyright 2012-2020 Jyri J. Virkki\n");
  printf("This program comes with ABSOLUTELY NO WARRANTY.\n");
  printf("This is free software, and you are welcome to redistribute it\n");
  printf("under certain conditions. Run 'dupd license' for details.\n");
  printf("\n");
}


decompiled_code:
int show_usage()
{
int result; // eax
__int64 v1; // rbx
int v2; // edi

show_banner();
result = man_dupd_len;
if ( man_dupd_len )
{
v1 = 0LL;
do
{
v2 = man_dupd[v1++];
result = putchar(v2);
}
while ( man_dupd_len > (unsigned int)v1 );
}
return result;
}

canonical_decompiled_code:
int func3()
{
int result; // eax
__int64 v1; // rbx
int v2; // edi

func2();
result = man_dupd_len;
if ( man_dupd_len )
{
v1 = 0LL;
do
{
v2 = man_dupd[v1++];
result = putchar(v2);
}
while ( man_dupd_len > (unsigned int)v1 );
}
return result;
}

original_code:
static void show_usage()
{
  show_banner();
  for (unsigned int c = 0; c < man_dupd_len; c++) {
    putchar((char)man_dupd[c]);
  }
}

variable_types:
c
unsigned int


decompiled_code:
__int64 operation_cache()
{
__int64 result; // rax

if ( cache_delete )
{
result = operation_cache_delete(cache_db_path);
if ( cache_ls )
result = ((__int64 (*)(void))operation_cache_ls)();
}
else
{
result = (unsigned int)cache_ls;
if ( cache_ls )
result = operation_cache_ls(cache_db_path);
}
return result;
}

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

if ( cache_delete )
{
result = operation_cache_delete(cache_db_path);
if ( cache_ls )
result = ((__int64 (*)(void))operation_cache_ls)();
}
else
{
result = (unsigned int)cache_ls;
if ( cache_ls )
result = operation_cache_ls(cache_db_path);
}
return result;
}

original_code:
static void operation_cache()
{
  if (cache_delete) { operation_cache_delete(cache_db_path); }
  if (cache_ls) { operation_cache_ls(cache_db_path); }
}


decompiled_code:
__int64 show_help()
{
show_banner();
printf("%% dupd operation options\n");
putchar(10);
return opt_show_help();
}

canonical_decompiled_code:
__int64 func5()
{
func2();
printf("%% dupd operation options\n");
putchar(10);
return opt_show_help();
}

original_code:
static void show_help()
{
  show_banner();
  printf("%% dupd operation options\n");
  printf("\n");
  opt_show_help();
}


decompiled_code:
__int64 __fastcall process_args(__int64 a1, __int64 a2)
{
unsigned int v2; // eax
unsigned int v3; // er12
unsigned int v4; // eax
int v5; // eax
int v6; // eax
_WORD *v7; // rax
__int64 v8; // rdi
const char *v9; // rbp
const char *v10; // rbp
unsigned __int64 v11; // rbp
const char *v12; // r13
const char *v13; // rdx
__int64 v14; // rbp
const char *v15; // r13
unsigned __int64 v16; // rax
unsigned __int64 v17; // rbx
double v18; // xmm0_8
double v19; // xmm0_8
double v20; // xmm0_8
double v21; // xmm0_8
char *v23; // rax
char *v24; // rbx
const char *v25; // rax
const char *v26; // rax
unsigned __int64 v27; // rbp
const char *v28; // rax
char *v29; // rax
char *v30; // rax
char *v31; // rax
char *v32; // rax
const char *v33; // rax
_QWORD v34[19]; // [rsp+0h] [rbp-158h] BYREF
char *src; // [rsp+98h] [rbp-C0h]
_BYTE *v36; // [rsp+A0h] [rbp-B8h]
__int64 v37; // [rsp+A8h] [rbp-B0h]
__int64 v38; // [rsp+B0h] [rbp-A8h]
__int64 v39; // [rsp+B8h] [rbp-A0h]
__int64 v40; // [rsp+C0h] [rbp-98h]
__int64 v41; // [rsp+C8h] [rbp-90h]
__int64 v42; // [rsp+D0h] [rbp-88h]
__int64 v43; // [rsp+D8h] [rbp-80h]
__int64 v44; // [rsp+E0h] [rbp-78h]
__int64 v45; // [rsp+E8h] [rbp-70h]
char *v46; // [rsp+F0h] [rbp-68h]
char *v47; // [rsp+F8h] [rbp-60h]
__int64 v48; // [rsp+100h] [rbp-58h]
__int64 v49; // [rsp+108h] [rbp-50h]
__int64 v50; // [rsp+110h] [rbp-48h]
__int64 v51; // [rsp+118h] [rbp-40h]
__int64 v52; // [rsp+120h] [rbp-38h]
__int64 v53; // [rsp+128h] [rbp-30h]

using_fiemap = 1;
v2 = optgen_parse(a1, a2, &operation, v34);
if ( v48 )
{
v3 = 1;
show_help();
return v3;
}
v3 = v2;
if ( v2 == 1 )
{
show_banner();
putchar(10);
puts("Run 'dupd help' for a summary of available options.");
puts("Run 'dupd usage' for more documentation.");
return v3;
}
if ( v2 )
{
v3 = 2;
puts("error parsing command line arguments");
return v3;
}
if ( v53 )
{
v4 = getpid();
printf("%d\n", v4);
getchar();
}
if ( v49 )
x_small_buffers = 1;
if ( v50 )
only_testing = 1;
if ( v45 )
log_level = -99;
log_level = opt_int(v44, (unsigned int)log_level);
v5 = log_level + opt_count(v43);
if ( v5 > 13 )
v5 = 13;
log_level = v5;
if ( !start_path_state )
{
start_path = (char *)malloc(0x1000uLL);
if ( !getcwd(start_path, 0x1000uLL) )
goto LABEL_123;
start_path_count = 1;
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v25 = (const char *)get_thread_name();
printf("%s", v25);
printf("Defaulting --path to [%s]\n", start_path);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
if ( src )
{
file_path = src;
if ( *src != 47 )
{
v23 = (char *)malloc(0x1000uLL);
free_file_path = 1;
file_path = v23;
if ( getcwd(v23, 0x1000uLL) )
{
v24 = file_path;
*(_WORD *)&v24[strlen(file_path)] = 47;
strcat(file_path, src);
goto LABEL_17;
}
LABEL_123:
v3 = 2;
puts("error: unable to get current directory");
return v3;
}
}
LABEL_17:
db_path = v46;
if ( !v46 )
{
v31 = (char *)malloc(0x1000uLL);
free_db_path = 1;
db_path = v31;
v32 = getenv("HOME");
snprintf(db_path, 0x1000uLL, "%s/.dupd_sqlite", v32);
}
cache_db_path = v47;
if ( !v47 )
{
v29 = (char *)malloc(0x1000uLL);
free_cache_db_path = 1;
cache_db_path = v29;
v30 = getenv("HOME");
snprintf(cache_db_path, 0x1000uLL, "%s/.dupd_cache", v30);
}
if ( v39 )
rmsh_link = 1;
if ( v40 )
rmsh_link = 2;
if ( v34[3] )
scan_hidden = 1;
if ( v34[8] )
threaded_sizetree = 0;
if ( v34[7] )
hardlink_is_unique = 1;
if ( v34[5] )
one_file_system = 1;
if ( v51 )
use_hash_cache = 0;
if ( v37 )
cache_delete = 1;
if ( v38 )
cache_ls = 1;
cache_min_size = (int)opt_int(v52, (unsigned int)cache_min_size);
hash_one_block_size = opt_int(v34[10], (unsigned int)hash_one_block_size);
hash_block_size = opt_int(v34[11], (unsigned int)hash_block_size);
filecmp_block_size = opt_int(v34[12], (unsigned int)filecmp_block_size);
hash_one_max_blocks = opt_int(v34[9], (unsigned int)hash_one_max_blocks);
debug_size = (int)opt_int(v34[16], (unsigned int)debug_size);
cut_path = v34[17];
exclude_path = (__int64)v36;
if ( v36 && *v36 != 47 )
{
v3 = 2;
puts("error: --exclude-path must be absolute");
return v3;
}
stats_file = v34[1];
trace_file = (char *)v34[6];
info_extents_path = v41;
v6 = opt_int(v34[2], (unsigned int)minimum_file_size);
if ( !v6 )
v6 = 1;
minimum_file_size = v6;
v7 = malloc(2uLL);
v8 = v42;
*v7 = (unsigned __int8)path_separator;
path_sep_string = v7;
v9 = (const char *)opt_string(v8, "xxhash");
if ( !strcmp("md5", v9) )
{
hash_function = 1;
}
else if ( !strcmp("sha1", v9) )
{
hash_function = 2;
}
else if ( !strcmp("sha512", v9) )
{
hash_function = 3;
}
else
{
if ( strcmp("xxhash", v9) )
{
v3 = 2;
printf("error: unknown hash %s\n", v9);
return v3;
}
hash_function = 4;
}
hash_bufsize = hash_get_bufsize((unsigned int)hash_function);
v10 = (const char *)opt_string(v34[18], "text");
if ( !strcmp("text", v10) )
{
report_format = 1;
}
else if ( !strcmp("csv", v10) )
{
report_format = 2;
}
else
{
if ( strcmp("json", v10) )
{
v3 = 2;
printf("error: unknown report format %s\n", v10);
return v3;
}
report_format = 3;
}
v11 = 0LL;
v12 = (const char *)opt_string(v34[4], "0");
if ( strcmp("0", v12) )
{
v13 = &v12[(int)strlen(v12) - 1];
if ( *v13 == 77 )
{
*v13 = 0;
v14 = 0x100000LL;
}
else
{
v14 = 1LL;
if ( *v13 == 71 )
{
*v13 = 0;
v14 = 0x40000000LL;
}
}
v11 = atol(v12) * v14;
if ( v11 < 0x800000 )
v11 = 0x800000LL;
}
if ( v34[13] )
opt_compare_two = 1;
if ( !hash_one_block_size )
hash_one_block_size = DEF_HDD_hash_one_block_size;
round1_max_bytes = hash_one_max_blocks * hash_one_block_size;
if ( !cache_min_size )
{
if ( (unsigned int)(hash_one_max_blocks * hash_one_block_size) > 0x7FFFF )
cache_min_size = (unsigned int)(hash_one_max_blocks * hash_one_block_size);
else
cache_min_size = 0x80000LL;
}
v15 = (const char *)opt_string(v34[14], "def");
if ( !strcmp("inode", v15) )
{
sort_bypass = 15;
}
else if ( !strcmp("block", v15) )
{
sort_bypass = 13;
}
else if ( !strcmp("none", v15) )
{
sort_bypass = 11;
}
else if ( !sort_bypass )
{
goto LABEL_69;
}
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v33 = (const char *)get_thread_name();
printf("%s", v33);
printf("Sort bypass set to %s\n", v15);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( hardlink_is_unique )
{
v3 = 2;
puts("Don't do that..");
return v3;
}
if ( sort_bypass && sort_bypass != 13 )
using_fiemap = 0;
LABEL_69:
if ( v34[15] )
using_fiemap = 0;
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v26 = (const char *)get_thread_name();
printf("%s", v26);
printf("Will be using_fiemap (if available): %d\n", (unsigned int)using_fiemap);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
v16 = total_ram();
v17 = v16;
if ( !v11 )
goto LABEL_79;
if ( v11 > v16 )
{
if ( (v16 & 0x8000000000000000LL) != 0LL )
v18 = (double)(int)(v16 & 1 | (v16 >> 1)) + (double)(int)(v16 & 1 | (v16 >> 1));
else
v18 = (double)(int)v16;
v19 = v18 * 0.9;
if ( v19 < 9.223372036854776e18 )
{
buffer_limit = (unsigned int)(int)v19;
}
else
{
buffer_limit = (unsigned int)(int)(v19 - 9.223372036854776e18);
buffer_limit ^= 0x8000000000000000LL;
}
LABEL_79:
if ( !buffer_limit )
{
v20 = (v16 & 0x8000000000000000LL) != 0LL ? (double)(int)(v16 & 1 | (v16 >> 1))
+ (double)(int)(v16 & 1 | (v16 >> 1)) : (double)(int)v16;
v21 = v20 * 0.5;
if ( v21 >= 9.223372036854776e18 )
{
buffer_limit = (unsigned int)(int)(v21 - 9.223372036854776e18);
buffer_limit ^= 0x8000000000000000LL;
}
else
{
buffer_limit = (unsigned int)(int)v21;
}
if ( x_small_buffers )
buffer_limit = 0x100000LL;
}
goto LABEL_86;
}
buffer_limit = v11;
LABEL_86:
if ( log_level > 3 )
{
v27 = buffer_limit;
pthread_mutex_lock(&logger_lock);
v28 = (const char *)get_thread_name();
printf("%s", v28);
printf("Reported RAM: %dMB buffer limit: %dMB\n", v17 >> 20, v27 >> 20);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( debug_size && log_level <= 2 )
log_level = 3;
return v3;
}

canonical_decompiled_code:
__int64 __fastcall func6(__int64 a1, __int64 a2)
{
unsigned int v2; // eax
unsigned int v3; // er12
unsigned int v4; // eax
int v5; // eax
int v6; // eax
_WORD *v7; // rax
__int64 v8; // rdi
const char *v9; // rbp
const char *v10; // rbp
unsigned __int64 v11; // rbp
const char *v12; // r13
const char *v13; // rdx
__int64 v14; // rbp
const char *v15; // r13
unsigned __int64 v16; // rax
unsigned __int64 v17; // rbx
double v18; // xmm0_8
double v19; // xmm0_8
double v20; // xmm0_8
double v21; // xmm0_8
char *v23; // rax
char *v24; // rbx
const char *v25; // rax
const char *v26; // rax
unsigned __int64 v27; // rbp
const char *v28; // rax
char *v29; // rax
char *v30; // rax
char *v31; // rax
char *v32; // rax
const char *v33; // rax
_QWORD v34[19]; // [rsp+0h] [rbp-158h] BYREF
char *src; // [rsp+98h] [rbp-C0h]
_BYTE *v36; // [rsp+A0h] [rbp-B8h]
__int64 v37; // [rsp+A8h] [rbp-B0h]
__int64 v38; // [rsp+B0h] [rbp-A8h]
__int64 v39; // [rsp+B8h] [rbp-A0h]
__int64 v40; // [rsp+C0h] [rbp-98h]
__int64 v41; // [rsp+C8h] [rbp-90h]
__int64 v42; // [rsp+D0h] [rbp-88h]
__int64 v43; // [rsp+D8h] [rbp-80h]
__int64 v44; // [rsp+E0h] [rbp-78h]
__int64 v45; // [rsp+E8h] [rbp-70h]
char *v46; // [rsp+F0h] [rbp-68h]
char *v47; // [rsp+F8h] [rbp-60h]
__int64 v48; // [rsp+100h] [rbp-58h]
__int64 v49; // [rsp+108h] [rbp-50h]
__int64 v50; // [rsp+110h] [rbp-48h]
__int64 v51; // [rsp+118h] [rbp-40h]
__int64 v52; // [rsp+120h] [rbp-38h]
__int64 v53; // [rsp+128h] [rbp-30h]

using_fiemap = 1;
v2 = optgen_parse(a1, a2, &operation, v34);
if ( v48 )
{
v3 = 1;
func5();
return v3;
}
v3 = v2;
if ( v2 == 1 )
{
func2();
putchar(10);
puts("Run 'dupd help' for a summary of available options.");
puts("Run 'dupd usage' for more documentation.");
return v3;
}
if ( v2 )
{
v3 = 2;
puts("error parsing command line arguments");
return v3;
}
if ( v53 )
{
v4 = getpid();
printf("%d\n", v4);
getchar();
}
if ( v49 )
x_small_buffers = 1;
if ( v50 )
only_testing = 1;
if ( v45 )
log_level = -99;
log_level = opt_int(v44, (unsigned int)log_level);
v5 = log_level + opt_count(v43);
if ( v5 > 13 )
v5 = 13;
log_level = v5;
if ( !start_path_state )
{
start_path = (char *)malloc(0x1000uLL);
if ( !getcwd(start_path, 0x1000uLL) )
goto LABEL_123;
start_path_count = 1;
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v25 = (const char *)get_thread_name();
printf("%s", v25);
printf("Defaulting --path to [%s]\n", start_path);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
if ( src )
{
file_path = src;
if ( *src != 47 )
{
v23 = (char *)malloc(0x1000uLL);
free_file_path = 1;
file_path = v23;
if ( getcwd(v23, 0x1000uLL) )
{
v24 = file_path;
*(_WORD *)&v24[strlen(file_path)] = 47;
strcat(file_path, src);
goto LABEL_17;
}
LABEL_123:
v3 = 2;
puts("error: unable to get current directory");
return v3;
}
}
LABEL_17:
db_path = v46;
if ( !v46 )
{
v31 = (char *)malloc(0x1000uLL);
free_db_path = 1;
db_path = v31;
v32 = getenv("HOME");
snprintf(db_path, 0x1000uLL, "%s/.dupd_sqlite", v32);
}
cache_db_path = v47;
if ( !v47 )
{
v29 = (char *)malloc(0x1000uLL);
free_cache_db_path = 1;
cache_db_path = v29;
v30 = getenv("HOME");
snprintf(cache_db_path, 0x1000uLL, "%s/.dupd_cache", v30);
}
if ( v39 )
rmsh_link = 1;
if ( v40 )
rmsh_link = 2;
if ( v34[3] )
scan_hidden = 1;
if ( v34[8] )
threaded_sizetree = 0;
if ( v34[7] )
hardlink_is_unique = 1;
if ( v34[5] )
one_file_system = 1;
if ( v51 )
use_hash_cache = 0;
if ( v37 )
cache_delete = 1;
if ( v38 )
cache_ls = 1;
cache_min_size = (int)opt_int(v52, (unsigned int)cache_min_size);
hash_one_block_size = opt_int(v34[10], (unsigned int)hash_one_block_size);
hash_block_size = opt_int(v34[11], (unsigned int)hash_block_size);
filecmp_block_size = opt_int(v34[12], (unsigned int)filecmp_block_size);
hash_one_max_blocks = opt_int(v34[9], (unsigned int)hash_one_max_blocks);
debug_size = (int)opt_int(v34[16], (unsigned int)debug_size);
cut_path = v34[17];
exclude_path = (__int64)v36;
if ( v36 && *v36 != 47 )
{
v3 = 2;
puts("error: --exclude-path must be absolute");
return v3;
}
stats_file = v34[1];
trace_file = (char *)v34[6];
info_extents_path = v41;
v6 = opt_int(v34[2], (unsigned int)minimum_file_size);
if ( !v6 )
v6 = 1;
minimum_file_size = v6;
v7 = malloc(2uLL);
v8 = v42;
*v7 = (unsigned __int8)path_separator;
path_sep_string = v7;
v9 = (const char *)opt_string(v8, "xxhash");
if ( !strcmp("md5", v9) )
{
hash_function = 1;
}
else if ( !strcmp("sha1", v9) )
{
hash_function = 2;
}
else if ( !strcmp("sha512", v9) )
{
hash_function = 3;
}
else
{
if ( strcmp("xxhash", v9) )
{
v3 = 2;
printf("error: unknown hash %s\n", v9);
return v3;
}
hash_function = 4;
}
hash_bufsize = hash_get_bufsize((unsigned int)hash_function);
v10 = (const char *)opt_string(v34[18], "text");
if ( !strcmp("text", v10) )
{
report_format = 1;
}
else if ( !strcmp("csv", v10) )
{
report_format = 2;
}
else
{
if ( strcmp("json", v10) )
{
v3 = 2;
printf("error: unknown report format %s\n", v10);
return v3;
}
report_format = 3;
}
v11 = 0LL;
v12 = (const char *)opt_string(v34[4], "0");
if ( strcmp("0", v12) )
{
v13 = &v12[(int)strlen(v12) - 1];
if ( *v13 == 77 )
{
*v13 = 0;
v14 = 0x100000LL;
}
else
{
v14 = 1LL;
if ( *v13 == 71 )
{
*v13 = 0;
v14 = 0x40000000LL;
}
}
v11 = atol(v12) * v14;
if ( v11 < 0x800000 )
v11 = 0x800000LL;
}
if ( v34[13] )
opt_compare_two = 1;
if ( !hash_one_block_size )
hash_one_block_size = DEF_HDD_hash_one_block_size;
round1_max_bytes = hash_one_max_blocks * hash_one_block_size;
if ( !cache_min_size )
{
if ( (unsigned int)(hash_one_max_blocks * hash_one_block_size) > 0x7FFFF )
cache_min_size = (unsigned int)(hash_one_max_blocks * hash_one_block_size);
else
cache_min_size = 0x80000LL;
}
v15 = (const char *)opt_string(v34[14], "def");
if ( !strcmp("inode", v15) )
{
sort_bypass = 15;
}
else if ( !strcmp("block", v15) )
{
sort_bypass = 13;
}
else if ( !strcmp("none", v15) )
{
sort_bypass = 11;
}
else if ( !sort_bypass )
{
goto LABEL_69;
}
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v33 = (const char *)get_thread_name();
printf("%s", v33);
printf("Sort bypass set to %s\n", v15);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( hardlink_is_unique )
{
v3 = 2;
puts("Don't do that..");
return v3;
}
if ( sort_bypass && sort_bypass != 13 )
using_fiemap = 0;
LABEL_69:
if ( v34[15] )
using_fiemap = 0;
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v26 = (const char *)get_thread_name();
printf("%s", v26);
printf("Will be using_fiemap (if available): %d\n", (unsigned int)using_fiemap);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
v16 = total_ram();
v17 = v16;
if ( !v11 )
goto LABEL_79;
if ( v11 > v16 )
{
if ( (v16 & 0x8000000000000000LL) != 0LL )
v18 = (double)(int)(v16 & 1 | (v16 >> 1)) + (double)(int)(v16 & 1 | (v16 >> 1));
else
v18 = (double)(int)v16;
v19 = v18 * 0.9;
if ( v19 < 9.223372036854776e18 )
{
buffer_limit = (unsigned int)(int)v19;
}
else
{
buffer_limit = (unsigned int)(int)(v19 - 9.223372036854776e18);
buffer_limit ^= 0x8000000000000000LL;
}
LABEL_79:
if ( !buffer_limit )
{
v20 = (v16 & 0x8000000000000000LL) != 0LL ? (double)(int)(v16 & 1 | (v16 >> 1))
+ (double)(int)(v16 & 1 | (v16 >> 1)) : (double)(int)v16;
v21 = v20 * 0.5;
if ( v21 >= 9.223372036854776e18 )
{
buffer_limit = (unsigned int)(int)(v21 - 9.223372036854776e18);
buffer_limit ^= 0x8000000000000000LL;
}
else
{
buffer_limit = (unsigned int)(int)v21;
}
if ( x_small_buffers )
buffer_limit = 0x100000LL;
}
goto LABEL_86;
}
buffer_limit = v11;
LABEL_86:
if ( log_level > 3 )
{
v27 = buffer_limit;
pthread_mutex_lock(&logger_lock);
v28 = (const char *)get_thread_name();
printf("%s", v28);
printf("Reported RAM: %dMB buffer limit: %dMB\n", v17 >> 20, v27 >> 20);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( debug_size && log_level <= 2 )
log_level = 3;
return v3;
}

original_code:
static int process_args(int argc, char * argv[])
{
  char * options[38];
  uint64_t user_ram_limit = 0;
  using_fiemap = 1;
  int rv = optgen_parse(argc, argv, &operation, options);
  if (options[32]) {
    show_help();
    return 1;
  }
  if (rv == 1) {
    show_banner();
    printf("\n");
    printf("Run 'dupd help' for a summary of available options.\n");
    printf("Run 'dupd usage' for more documentation.\n");
    return 1;
  }
  if (rv != 0) {
    printf("error parsing command line arguments\n");
    return 2;
  }
  if (options[37]) {
    printf("%d\n", getpid());
    getchar();
  }
  if (options[33]) { x_small_buffers = 1; }
  if (options[34]) { only_testing = 1; }
  if (options[29]) { log_level = -99; }
  log_level = opt_int(options[28], log_level);
  log_level += opt_count(options[27]);
  if (log_level > 13) { log_level = 13; }
  if (start_path_state == 0) {
    start_path[0] = (char *)malloc(4096);
    if (!getcwd(start_path[0], 4096)) {
      printf("error: unable to get current directory\n");
      return 2;
    }
    start_path_count = 1;
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Defaulting --path to [%s]\n", start_path[0]); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  if (options[19] != ((void *)0)) {
    file_path = options[19];
    if (file_path[0] != '/') {
      file_path = (char *)malloc(4096);
      free_file_path = 1;
      if (!getcwd(file_path, 4096)) {
        printf("error: unable to get current directory\n");
        return 2;
      }
      strcat(file_path, "/");
      strcat(file_path, options[19]);
    }
  }
  db_path = options[30];
  if (db_path == ((void *)0)) {
    db_path = (char *)malloc(4096);
    free_db_path = 1;
    snprintf(db_path, 4096, "%s/.dupd_sqlite", getenv("HOME"));
  }
  cache_db_path = options[31];
  if (cache_db_path == ((void *)0)) {
    cache_db_path = (char *)malloc(4096);
    free_cache_db_path = 1;
    snprintf(cache_db_path, 4096, "%s/.dupd_cache", getenv("HOME"));
  }
  if (options[23]) { rmsh_link = 1; }
  if (options[24]) { rmsh_link = 2; }
  if (options[3]) { scan_hidden = 1; }
  if (options[8]) { threaded_sizetree = 0; }
  if (options[7]) { hardlink_is_unique = 1; }
  if (options[5]) { one_file_system = 1; }
  if (options[35]) { use_hash_cache = 0; }
  if (options[21]) { cache_delete = 1; }
  if (options[22]) { cache_ls = 1; }
  cache_min_size =
    (uint64_t)opt_int(options[36], cache_min_size);
  hash_one_block_size = opt_int(options[10],
                                hash_one_block_size);
  hash_block_size = opt_int(options[11], hash_block_size);
  filecmp_block_size = opt_int(options[12], filecmp_block_size);
  hash_one_max_blocks = opt_int(options[9], hash_one_max_blocks);
  debug_size = opt_int(options[16], debug_size);
  cut_path = options[17];
  exclude_path = options[20];
  if (exclude_path != ((void *)0) && exclude_path[0] != '/') {
    printf("error: --exclude-path must be absolute\n");
    return 2;
  }
  stats_file = options[1];
  trace_file = options[6];
  info_extents_path = options[25];
  minimum_file_size = opt_int(options[2], minimum_file_size);
  if (minimum_file_size < 1) { minimum_file_size = 1; }
  path_sep_string = (char *)malloc(2);
  path_sep_string[0] = (char)path_separator;
  path_sep_string[1] = 0;
  char * hash_name = opt_string(options[26], "xxhash");
  if (!strcmp("md5", hash_name)) {
    hash_function = 1;
  } else if (!strcmp("sha1", hash_name)) {
    hash_function = 2;
  } else if (!strcmp("sha512", hash_name)) {
    hash_function = 3;
  } else if (!strcmp("xxhash", hash_name)) {
    hash_function = 4;
  } else {
    printf("error: unknown hash %s\n", hash_name);
    return 2;
  }
  hash_bufsize = hash_get_bufsize(hash_function);
  char * report_format_name = opt_string(options[18], "text");
  if (!strcmp("text", report_format_name)) {
    report_format = 1;
  } else if (!strcmp("csv", report_format_name)) {
    report_format = 2;
  } else if (!strcmp("json", report_format_name)) {
    report_format = 3;
  } else {
    printf("error: unknown report format %s\n", report_format_name);
    return 2;
  }
  char * buflimstr = opt_string(options[4], "0");
  if (strcmp("0", buflimstr)) {
    int len = strlen(buflimstr);
    if (buflimstr[len-1] == 'M') {
      user_ram_limit = (1024 * 1024);
      buflimstr[len-1] = 0;
    } else if (buflimstr[len-1] == 'G') {
      user_ram_limit = (1024 * 1024 * 1024);
      buflimstr[len-1] = 0;
    } else {
      user_ram_limit = 1;
    }
    long c = atol(buflimstr);
    user_ram_limit *= c;
    if (user_ram_limit < (1024 * 1024 * 8)) {
      user_ram_limit = (1024 * 1024 * 8);
    }
  }
  if (options[13]) {
    opt_compare_two = 1;
  }
  if (hash_one_block_size == 0) {
    hash_one_block_size = DEF_HDD_hash_one_block_size;
  }
  round1_max_bytes = hash_one_block_size * hash_one_max_blocks;
  if (cache_min_size == 0) {
    if (round1_max_bytes < (1024 * 512)) {
      cache_min_size = (1024 * 512);
    } else {
      cache_min_size = round1_max_bytes;
    }
  }
  char * sortby = opt_string(options[14], "def");
  if (!strcmp("inode", sortby)) {
    sort_bypass = 15;
  } else if (!strcmp("block", sortby)) {
    sort_bypass = 13;
  } else if (!strcmp("none", sortby)) {
    sort_bypass = 11;
  }
  if (sort_bypass != 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Sort bypass set to %s\n", sortby); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    if (hardlink_is_unique) {
      printf("Don't do that..\n");
      return 2;
    }
  }
  if (sort_bypass != 0 && sort_bypass != 13) {
    using_fiemap = 0;
  }
  if (options[15]) { using_fiemap = 0; }
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Will be using_fiemap (if available): %d\n", using_fiemap); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  uint64_t ram = total_ram();
  if (user_ram_limit > 0) {
    if (user_ram_limit > ram) {
      buffer_limit = 0.9 * ram;
    } else {
      buffer_limit = user_ram_limit;
    }
  }
  if (buffer_limit == 0) {
    buffer_limit = 0.5 * ram;
    if (x_small_buffers) {
      buffer_limit = (1024 * 1024);
    }
  }
  int ramm = ram / (1024 * 1024);
  int blim = buffer_limit / (1024 * 1024);
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Reported RAM: %dMB  buffer limit: %dMB\n", ramm, blim); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  if (debug_size) {
    if (log_level < 3) { log_level = 3; }
  }
  return 0;
}

canonical_original_code:
static int process_args(int argc, char *argv[])
{
  char *options[38];
  unsigned long user_ram_limit = 0;
  using_fiemap = 1;
  int rv = optgen_parse(argc, argv, &operation, options);
  if (options[32]) {
    show_help();
    return 1;
  }
  if (rv == 1) {
    show_banner();
    printf("\n");
    printf("Run 'dupd help' for a summary of available options.\n");
    printf("Run 'dupd usage' for more documentation.\n");
    return 1;
  }
  if (rv != 0) {
    printf("error parsing command line arguments\n");
    return 2;
  }
  if (options[37]) {
    printf("%d\n", getpid());
    getchar();
  }
  if (options[33]) { x_small_buffers = 1; }
  if (options[34]) { only_testing = 1; }
  if (options[29]) { log_level = -99; }
  log_level = opt_int(options[28], log_level);
  log_level += opt_count(options[27]);
  if (log_level > 13) { log_level = 13; }
  if (start_path_state == 0) {
    start_path[0] = (char *)malloc(4096);
    if (!getcwd(start_path[0], 4096)) {
      printf("error: unable to get current directory\n");
      return 2;
    }
    start_path_count = 1;
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Defaulting --path to [%s]\n", start_path[0]); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  if (options[19] != ((void *)0)) {
    file_path = options[19];
    if (file_path[0] != '/') {
      file_path = (char *)malloc(4096);
      free_file_path = 1;
      if (!getcwd(file_path, 4096)) {
        printf("error: unable to get current directory\n");
        return 2;
      }
      strcat(file_path, "/");
      strcat(file_path, options[19]);
    }
  }
  db_path = options[30];
  if (db_path == ((void *)0)) {
    db_path = (char *)malloc(4096);
    free_db_path = 1;
    snprintf(db_path, 4096, "%s/.dupd_sqlite", getenv("HOME"));
  }
  cache_db_path = options[31];
  if (cache_db_path == ((void *)0)) {
    cache_db_path = (char *)malloc(4096);
    free_cache_db_path = 1;
    snprintf(cache_db_path, 4096, "%s/.dupd_cache", getenv("HOME"));
  }
  if (options[23]) { rmsh_link = 1; }
  if (options[24]) { rmsh_link = 2; }
  if (options[3]) { scan_hidden = 1; }
  if (options[8]) { threaded_sizetree = 0; }
  if (options[7]) { hardlink_is_unique = 1; }
  if (options[5]) { one_file_system = 1; }
  if (options[35]) { use_hash_cache = 0; }
  if (options[21]) { cache_delete = 1; }
  if (options[22]) { cache_ls = 1; }
  cache_min_size =
    (unsigned long)opt_int(options[36], cache_min_size);
  hash_one_block_size = opt_int(options[10],
                                hash_one_block_size);
  hash_block_size = opt_int(options[11], hash_block_size);
  filecmp_block_size = opt_int(options[12], filecmp_block_size);
  hash_one_max_blocks = opt_int(options[9], hash_one_max_blocks);
  debug_size = opt_int(options[16], debug_size);
  cut_path = options[17];
  exclude_path = options[20];
  if (exclude_path != ((void *)0) && exclude_path[0] != '/') {
    printf("error: --exclude-path must be absolute\n");
    return 2;
  }
  stats_file = options[1];
  trace_file = options[6];
  info_extents_path = options[25];
  minimum_file_size = opt_int(options[2], minimum_file_size);
  if (minimum_file_size < 1) { minimum_file_size = 1; }
  path_sep_string = (char *)malloc(2);
  path_sep_string[0] = (char)path_separator;
  path_sep_string[1] = 0;
  char *hash_name = opt_string(options[26], "xxhash");
  if (!strcmp("md5", hash_name)) {
    hash_function = 1;
  } else if (!strcmp("sha1", hash_name)) {
    hash_function = 2;
  } else if (!strcmp("sha512", hash_name)) {
    hash_function = 3;
  } else if (!strcmp("xxhash", hash_name)) {
    hash_function = 4;
  } else {
    printf("error: unknown hash %s\n", hash_name);
    return 2;
  }
  hash_bufsize = hash_get_bufsize(hash_function);
  char *report_format_name = opt_string(options[18], "text");
  if (!strcmp("text", report_format_name)) {
    report_format = 1;
  } else if (!strcmp("csv", report_format_name)) {
    report_format = 2;
  } else if (!strcmp("json", report_format_name)) {
    report_format = 3;
  } else {
    printf("error: unknown report format %s\n", report_format_name);
    return 2;
  }
  char *buflimstr = opt_string(options[4], "0");
  if (strcmp("0", buflimstr)) {
    int len = strlen(buflimstr);
    if (buflimstr[len-1] == 'M') {
      user_ram_limit = (1024 * 1024);
      buflimstr[len-1] = 0;
    } else if (buflimstr[len-1] == 'G') {
      user_ram_limit = (1024 * 1024 * 1024);
      buflimstr[len-1] = 0;
    } else {
      user_ram_limit = 1;
    }
    long c = atol(buflimstr);
    user_ram_limit *= c;
    if (user_ram_limit < (1024 * 1024 * 8)) {
      user_ram_limit = (1024 * 1024 * 8);
    }
  }
  if (options[13]) {
    opt_compare_two = 1;
  }
  if (hash_one_block_size == 0) {
    hash_one_block_size = DEF_HDD_hash_one_block_size;
  }
  round1_max_bytes = hash_one_block_size * hash_one_max_blocks;
  if (cache_min_size == 0) {
    if (round1_max_bytes < (1024 * 512)) {
      cache_min_size = (1024 * 512);
    } else {
      cache_min_size = round1_max_bytes;
    }
  }
  char *sortby = opt_string(options[14], "def");
  if (!strcmp("inode", sortby)) {
    sort_bypass = 15;
  } else if (!strcmp("block", sortby)) {
    sort_bypass = 13;
  } else if (!strcmp("none", sortby)) {
    sort_bypass = 11;
  }
  if (sort_bypass != 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Sort bypass set to %s\n", sortby); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    if (hardlink_is_unique) {
      printf("Don't do that..\n");
      return 2;
    }
  }
  if (sort_bypass != 0 && sort_bypass != 13) {
    using_fiemap = 0;
  }
  if (options[15]) { using_fiemap = 0; }
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Will be using_fiemap (if available): %d\n", using_fiemap); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  unsigned long ram = total_ram();
  if (user_ram_limit > 0) {
    if (user_ram_limit > ram) {
      buffer_limit = 0.9 * ram;
    } else {
      buffer_limit = user_ram_limit;
    }
  }
  if (buffer_limit == 0) {
    buffer_limit = 0.5 * ram;
    if (x_small_buffers) {
      buffer_limit = (1024 * 1024);
    }
  }
  int ramm = ram / (1024 * 1024);
  int blim = buffer_limit / (1024 * 1024);
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Reported RAM: %dMB  buffer limit: %dMB\n", ramm, blim); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  if (debug_size) {
    if (log_level < 3) { log_level = 3; }
  }
  return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types:
options
char *[38]

variable_types:
buflimstr
char *

variable_types: len int

variable_types: c long

variable_types:
sortby
char *

variable_types:
ram
unsigned long

variable_types: ramm int

variable_types: blim int


decompiled_code:
__int64 __fastcall opt_add_path(const char *a1)
{
__int64 v1; // rbx
char *v2; // rax
int v3; // er14
__int64 v4; // rbx
const char *v5; // r12
const char *v6; // rbp
__int64 v7; // rbx
int v9; // er14
_WORD v10[92]; // [rsp+0h] [rbp-B8h] BYREF

if ( !start_path_state )
start_path_state = 1;
v1 = start_path_count;
v2 = realpath(a1, 0LL);
(&start_path)[v1] = v2;
if ( (unsigned int)get_file_info(v2, v10) || (v10[12] & 0xF000) != 0x4000 )
{
printf("error: not a directory: %s\n", (&start_path)[start_path_count]);
LABEL_12:
v7 = start_path_count;
free((&start_path)[start_path_count]);
(&start_path)[v7] = 0LL;
start_path_state = 2;
return 0LL;
}
v3 = start_path_count;
if ( start_path_count > 0 )
{
v4 = 0LL;
v5 = (&start_path)[start_path_count];
while ( 1 )
{
v6 = (&start_path)[v4];
if ( strstr(v6, v5) || strstr(v5, v6) )
break;
if ( ++v4 == v3 )
goto LABEL_14;
}
printf("error: overlap between %s and %s\n", v6, v5);
goto LABEL_12;
}
LABEL_14:
v9 = v3 + 1;
start_path_count = v9;
if ( v9 == 10 )
{
puts("error: exceeded max number of --path elements");
exit(1);
}
(&start_path)[v9] = 0LL;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func7(const char *a1)
{
__int64 v1; // rbx
char *v2; // rax
int v3; // er14
__int64 v4; // rbx
const char *v5; // r12
const char *v6; // rbp
__int64 v7; // rbx
int v9; // er14
_WORD v10[92]; // [rsp+0h] [rbp-B8h] BYREF

if ( !start_path_state )
start_path_state = 1;
v1 = start_path_count;
v2 = realpath(a1, 0LL);
(&start_path)[v1] = v2;
if ( (unsigned int)get_file_info(v2, v10) || (v10[12] & 0xF000) != 0x4000 )
{
printf("error: not a directory: %s\n", (&start_path)[start_path_count]);
LABEL_12:
v7 = start_path_count;
free((&start_path)[start_path_count]);
(&start_path)[v7] = 0LL;
start_path_state = 2;
return 0LL;
}
v3 = start_path_count;
if ( start_path_count > 0 )
{
v4 = 0LL;
v5 = (&start_path)[start_path_count];
while ( 1 )
{
v6 = (&start_path)[v4];
if ( strstr(v6, v5) || strstr(v5, v6) )
break;
if ( ++v4 == v3 )
goto LABEL_14;
}
printf("error: overlap between %s and %s\n", v6, v5);
goto LABEL_12;
}
LABEL_14:
v9 = v3 + 1;
start_path_count = v9;
if ( v9 == 10 )
{
puts("error: exceeded max number of --path elements");
exit(1);
}
(&start_path)[v9] = 0LL;
return 0LL;
}

original_code:
int opt_add_path(char * arg, int command)
{
  (void)command;
  if (start_path_state == 0) {
    start_path_state = 1;
  }
  start_path[start_path_count] = realpath(arg, ((void *)0));
  struct stat info;
  if (get_file_info(start_path[start_path_count], &info) ||
      !((((info.st_mode)) & 0170000) == (0040000))) {
    printf("error: not a directory: %s\n", start_path[start_path_count]);
    free(start_path[start_path_count]);
    start_path[start_path_count] = ((void *)0);
    start_path_state = 2;
    return 0;
  }
  for (int n = 0; n < start_path_count; n++) {
    if (strstr(start_path[n], start_path[start_path_count]) ||
        strstr(start_path[start_path_count], start_path[n])) {
      printf("error: overlap between %s and %s\n",
             start_path[n], start_path[start_path_count]);
      free(start_path[start_path_count]);
      start_path[start_path_count] = ((void *)0);
      start_path_state = 2;
      return 0;
    }
  }
  start_path_count++;
  if (start_path_count == 10) {
    printf("error: exceeded max number of --path elements\n");
    exit(1);
  }
  start_path[start_path_count] = ((void *)0);
  return 0;
}

canonical_original_code:
int opt_add_path(char *arg, int command)
{
  (void)command;
  if (start_path_state == 0) {
    start_path_state = 1;
  }
  start_path[start_path_count] = realpath(arg, ((void *)0));
  struct stat info;
  if (get_file_info(start_path[start_path_count], &info) ||
      !((((info.st_mode)) & 0170000) == (0040000))) {
    printf("error: not a directory: %s\n", start_path[start_path_count]);
    free(start_path[start_path_count]);
    start_path[start_path_count] = ((void *)0);
    start_path_state = 2;
    return 0;
  }
  for (int n = 0; n < start_path_count; n++) {
    if (strstr(start_path[n], start_path[start_path_count]) ||
        strstr(start_path[start_path_count], start_path[n])) {
      printf("error: overlap between %s and %s\n",
             start_path[n], start_path[start_path_count]);
      free(start_path[start_path_count]);
      start_path[start_path_count] = ((void *)0);
      start_path_state = 2;
      return 0;
    }
  }
  start_path_count++;
  if (start_path_count == 10) {
    printf("error: exceeded max number of --path elements\n");
    exit(1);
  }
  start_path[start_path_count] = ((void *)0);
  return 0;
}

variable_types:
arg
char *

variable_types: command int

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]; }

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]; }


main

canonical_name: main

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

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);
v10 = (const char *)get_thread_name();
printf("%s", v10);
printf("Log level: %s\n", log_level_name[log_level]);
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);
v12 = (const char *)get_thread_name();
printf("%s", v12);
v13 = cpu_cores();
printf("Claimed CPU cores: %d\n", v13);
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) )
{
printf("error: unable to create trace-file [%s]\n", trace_file);
}
else
{
switch ( operation )
{
case -1:
v3 = 1;
show_help();
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:
v3 = 1;
printf("error: unknown operation [%d]\n", (unsigned int)operation);
break;
}
}
}
v4 = (unsigned int)free_file_path;
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, v4, v6) - stats_main_start;
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v9 = (const char *)get_thread_name();
printf("%s", v9);
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; // er12
__int64 v4; // rsi
__int64 v5; // rdi
__int64 v6; // rdx
int v7; // eax
const char *v9; // rax
const char *v10; // rax
const char *v11; // rax
const char *v12; // rax
unsigned int v13; // eax

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);
v10 = (const char *)get_thread_name();
printf("%s", v10);
printf("Log level: %s\n", log_level_name[log_level]);
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);
v12 = (const char *)get_thread_name();
printf("%s", v12);
v13 = cpu_cores();
printf("Claimed CPU cores: %d\n", v13);
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) )
{
printf("error: unable to create trace-file [%s]\n", trace_file);
}
else
{
switch ( operation )
{
case -1:
v3 = 1;
func5();
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:
v3 = 1;
printf("error: unknown operation [%d]\n", (unsigned int)operation);
break;
}
}
}
v4 = (unsigned int)free_file_path;
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, v4, v6) - stats_main_start;
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v9 = (const char *)get_thread_name();
printf("%s", v9);
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


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; } *

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)
{
__int64 v3; // rdi
__int64 v5; // rax

v3 = *(_QWORD *)(a1 + 32);
if ( !v3 )
{
v5 = hash_fn_buf_init();
*(_QWORD *)(a1 + 32) = v5;
v3 = v5;
}
hash_fn_buf_update(v3, *(_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)
{
__int64 v3; // rdi
__int64 v5; // rax

v3 = *(_QWORD *)(a1 + 32);
if ( !v3 )
{
v5 = hash_fn_buf_init();
*(_QWORD *)(a1 + 32) = v5;
v3 = v5;
}
hash_fn_buf_update(v3, *(_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; } *

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; // rdx
__int64 result; // rax

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

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

v2 = *((_QWORD *)a2 + 2);
result = 1LL;
if ( *((_QWORD *)a1 + 2) <= v2 )
result = (unsigned int)-(*((_QWORD *)a1 + 2) < v2);
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:
size_t __fastcall add_one_to_inode_read_list(__int64 a1, __int64 a2, __int64 a3)
{
size_t result; // rax
bool v4; // zf
char *v5; // rcx
size_t v6; // rsi

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

canonical_decompiled_code:
size_t __fastcall func5(__int64 a1, __int64 a2, __int64 a3)
{
size_t result; // rax
bool v4; // zf
char *v5; // rcx
size_t v6; // rsi

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

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()
{
unsigned int v0; // ebp
size_t v1; // rdi

if ( hardlink_is_unique )
{
inode_read_list_size = 100000LL;
if ( x_small_buffers )
{
inode_read_list_size = 8LL;
v0 = 320;
v1 = 8LL;
}
else
{
v0 = 4000000;
v1 = 100000LL;
}
inode_read_list_end = 0LL;
inode_read_list = calloc(v1, 0x28uLL);
inc_stats_readlist(v0);
}
}

canonical_decompiled_code:
void func8()
{
unsigned int v0; // ebp
size_t v1; // rdi

if ( hardlink_is_unique )
{
inode_read_list_size = 100000LL;
if ( x_small_buffers )
{
inode_read_list_size = 8LL;
v0 = 320;
v1 = 8LL;
}
else
{
v0 = 4000000;
v1 = 100000LL;
}
inode_read_list_end = 0LL;
inode_read_list = calloc(v1, 0x28uLL);
inc_stats_readlist(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:
size_t __fastcall add_to_read_list(__int64 a1, __int64 a2, __int64 a3)
{
unsigned __int8 *v3; // rax
size_t result; // 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;
result = hardlink_is_unique;
if ( hardlink_is_unique )
result = add_one_to_inode_read_list(a1, a2, a3);
return result;
}

canonical_decompiled_code:
size_t __fastcall func10(__int64 a1, __int64 a2, __int64 a3)
{
unsigned __int8 *v3; // rax
size_t result; // 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;
result = hardlink_is_unique;
if ( hardlink_is_unique )
result = func5(a1, a2, a3);
return result;
}

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);
  }
}