// File: williewillus[P]panda_scratchpad/src/wrapper/wrapper.cpp
// Function: wrapper::RecordCmFsOps::CmWrite(int, void const*, unsigned long)
int RecordCmFsOps::CmWrite(const int fd, const void *buf, const size_t count) {
  DiskMod mod;
  mod.mod_opts = DiskMod::kNoneOpt;
  // Get current file position and size. If stat fails, then assume lseek will
  // fail too and just bail out.
  struct stat pre_stat_buf;
  // This could be an fstat(), but I don't see a reason to add another call that
  // does only reads to the already large interface of FsFns.
  int res = fns_->FnStat(fd_map_.at(fd), &pre_stat_buf);
  if (res < 0) {
    return res;
  }

  mod.file_mod_location = fns_->FnLseek(fd, 0, SEEK_CUR);
  if (mod.file_mod_location < 0) {
    return mod.file_mod_location;
  }

  const int write_res = fns_->FnWrite(fd, buf, count);
  if (write_res < 0) {
    return write_res;
  }

  mod.directory_mod = S_ISDIR(pre_stat_buf.st_mode);

  // TODO(ashmrtn): Support calling write directly on a directory.
  if (!mod.directory_mod) {
    // Copy over as much data as was written and see what the new file size is.
    // This will determine how we set the type of the DiskMod.
    mod.file_mod_len = write_res;
    mod.path = fd_map_.at(fd);

    res = fns_->FnStat(fd_map_.at(fd), &mod.post_mod_stats);
    if (res < 0) {
      return write_res;
    }

    if (pre_stat_buf.st_size != mod.post_mod_stats.st_size) {
      mod.mod_type = DiskMod::kDataMetadataMod;
    } else {
      mod.mod_type = DiskMod::kDataMod;
    }

    if (write_res > 0) {
      mod.file_mod_data.reset(new char[write_res], [](char* c) {delete[] c;});
      memcpy(mod.file_mod_data.get(), buf, write_res);
    }
  }

  mods_.push_back(mod);

  return write_res;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x240, %rsp            # imm = 0x240
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1f0(%rbp)
leaq -0x128(%rbp), %rdi
callq 0xe650
movq -0x1f0(%rbp), %rdi
movl $0x0, -0x104(%rbp)
movq 0x90(%rdi), %rax
movq %rax, -0x1e8(%rbp)
addq $0x8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x13ee0
movq %rax, -0x1e0(%rbp)
jmp 0x105b6
movq -0x1e0(%rbp), %rsi
movq -0x1e8(%rbp), %rdi
movq (%rdi), %rax
movq 0x88(%rax), %rax
leaq -0x1b8(%rbp), %rdx
callq *%rax
movl %eax, -0x1f4(%rbp)
jmp 0x105df
movl -0x1f4(%rbp), %eax
movl %eax, -0x1bc(%rbp)
cmpl $0x0, -0x1bc(%rbp)
jge 0x1062f
movl -0x1bc(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x1d0(%rbp)
jmp 0x10882
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1c8(%rbp)
movl %eax, -0x1cc(%rbp)
leaq -0x128(%rbp), %rdi
callq 0xbf60
jmp 0x1089a
movq -0x1f0(%rbp), %rax
movq 0x90(%rax), %rdi
movl -0x14(%rbp), %esi
movq (%rdi), %rax
movq 0x30(%rax), %rax
xorl %ecx, %ecx
movl %ecx, %edx
movl $0x1, %ecx
callq *%rax
movq %rax, -0x200(%rbp)
jmp 0x1065b
movq -0x200(%rbp), %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
jae 0x10683
movq -0x58(%rbp), %rax
movl %eax, -0x4(%rbp)
movl $0x1, -0x1d0(%rbp)
jmp 0x10882
movq -0x1f0(%rbp), %rax
movq 0x90(%rax), %rdi
movl -0x14(%rbp), %esi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq (%rdi), %rax
movq 0x38(%rax), %rax
callq *%rax
movq %rax, -0x208(%rbp)
jmp 0x106ae
movq -0x208(%rbp), %rax
movl %eax, -0x1d4(%rbp)
cmpl $0x0, -0x1d4(%rbp)
jge 0x106dc
movl -0x1d4(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x1d0(%rbp)
jmp 0x10882
movl -0x1a0(%rbp), %eax
andl $0xf000, %eax           # imm = 0xF000
cmpl $0x4000, %eax           # imm = 0x4000
sete %al
andb $0x1, %al
movb %al, -0x70(%rbp)
testb $0x1, -0x70(%rbp)
jne 0x10856
movq -0x1f0(%rbp), %rdi
movslq -0x1d4(%rbp), %rax
movq %rax, -0x50(%rbp)
addq $0x8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x13ee0
movq %rax, -0x210(%rbp)
jmp 0x10726
movq -0x210(%rbp), %rsi
leaq -0x128(%rbp), %rdi
callq 0x6060
jmp 0x1073b
movq -0x1f0(%rbp), %rdi
movq 0x90(%rdi), %rax
movq %rax, -0x220(%rbp)
addq $0x8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x13ee0
movq %rax, -0x218(%rbp)
jmp 0x10766
movq -0x218(%rbp), %rsi
movq -0x220(%rbp), %rdi
leaq -0x100(%rbp), %rdx
movq (%rdi), %rax
movq 0x88(%rax), %rax
callq *%rax
movl %eax, -0x224(%rbp)
jmp 0x1078f
movl -0x224(%rbp), %eax
movl %eax, -0x1bc(%rbp)
cmpl $0x0, -0x1bc(%rbp)
jge 0x107bc
movl -0x1d4(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x1d0(%rbp)
jmp 0x10882
movq -0x188(%rbp), %rax
cmpq -0xd0(%rbp), %rax
je 0x107d8
movl $0x1, -0x108(%rbp)
jmp 0x107e2
movl $0x3, -0x108(%rbp)
cmpl $0x0, -0x1d4(%rbp)
jle 0x10854
leaq -0x68(%rbp), %rax
movq %rax, -0x238(%rbp)
movslq -0x1d4(%rbp), %rdi
testq %rdi, %rdi
movq $-0x1, %rax
cmovsq %rax, %rdi
callq 0x6030
movq %rax, -0x230(%rbp)
jmp 0x10819
movq -0x230(%rbp), %rsi
movq -0x238(%rbp), %rdi
callq 0x108b0
jmp 0x1082e
leaq -0x128(%rbp), %rdi
addq $0xc0, %rdi
callq 0xf430
movq %rax, %rdi
movq -0x20(%rbp), %rsi
movslq -0x1d4(%rbp), %rdx
callq 0x6450
jmp 0x10856
movq -0x1f0(%rbp), %rdi
addq $0x78, %rdi
leaq -0x128(%rbp), %rsi
callq 0x13df0
jmp 0x1086f
movl -0x1d4(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x1d0(%rbp)
leaq -0x128(%rbp), %rdi
callq 0xbf60
movl -0x4(%rbp), %eax
addq $0x240, %rsp            # imm = 0x240
popq %rbp
retq
movq -0x1c8(%rbp), %rdi
callq 0x68a0
nopw %cs:(%rax,%rax)