// File: williewillus[P]panda_scratchpad/src/wrapper/wrapper.cpp
// Function: wrapper::RecordCmFsOps::CmPwrite(int, void const*, unsigned long, long)
ssize_t RecordCmFsOps::CmPwrite(const int fd, const void *buf,
    const size_t count, const off_t offset) {
  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;
  }

  const int write_res = fns_->FnPwrite(fd, buf, count, offset);
  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_location = offset;
    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;
  return fns_->FnPwrite(fd, buf, count, offset);
}

// 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 %r8, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1f8(%rbp)
leaq -0x130(%rbp), %rdi
callq 0xe650
movq -0x1f8(%rbp), %rdi
movl $0x0, -0x10c(%rbp)
movq 0x90(%rdi), %rax
movq %rax, -0x1f0(%rbp)
addq $0x8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x13ee0
movq %rax, -0x1e8(%rbp)
jmp 0x1096a
movq -0x1e8(%rbp), %rsi
movq -0x1f0(%rbp), %rdi
movq (%rdi), %rax
movq 0x88(%rax), %rax
leaq -0x1c0(%rbp), %rdx
callq *%rax
movl %eax, -0x1fc(%rbp)
jmp 0x10993
movl -0x1fc(%rbp), %eax
movl %eax, -0x1c4(%rbp)
cmpl $0x0, -0x1c4(%rbp)
jge 0x109e5
movslq -0x1c4(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x1d8(%rbp)
jmp 0x10bf6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x130(%rbp), %rdi
callq 0xbf60
jmp 0x10c0f
movq -0x1f8(%rbp), %rax
movq 0x90(%rax), %rdi
movl -0x14(%rbp), %esi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %r8
movq (%rdi), %rax
movq 0x40(%rax), %rax
callq *%rax
movq %rax, -0x208(%rbp)
jmp 0x10a14
movq -0x208(%rbp), %rax
movl %eax, -0x1dc(%rbp)
cmpl $0x0, -0x1dc(%rbp)
jge 0x10a44
movslq -0x1dc(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x1d8(%rbp)
jmp 0x10bf6
movl -0x1a8(%rbp), %eax
andl $0xf000, %eax           # imm = 0xF000
cmpl $0x4000, %eax           # imm = 0x4000
sete %al
andb $0x1, %al
movb %al, -0x78(%rbp)
testb $0x1, -0x78(%rbp)
jne 0x10bc8
movq -0x1f8(%rbp), %rdi
movq -0x30(%rbp), %rax
movq %rax, -0x60(%rbp)
movslq -0x1dc(%rbp), %rax
movq %rax, -0x58(%rbp)
addq $0x8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x13ee0
movq %rax, -0x210(%rbp)
jmp 0x10a96
movq -0x210(%rbp), %rsi
leaq -0x130(%rbp), %rdi
callq 0x6060
jmp 0x10aab
movq -0x1f8(%rbp), %rdi
movq 0x90(%rdi), %rax
movq %rax, -0x220(%rbp)
addq $0x8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x13ee0
movq %rax, -0x218(%rbp)
jmp 0x10ad6
movq -0x218(%rbp), %rsi
movq -0x220(%rbp), %rdi
leaq -0x108(%rbp), %rdx
movq (%rdi), %rax
movq 0x88(%rax), %rax
callq *%rax
movl %eax, -0x224(%rbp)
jmp 0x10aff
movl -0x224(%rbp), %eax
movl %eax, -0x1c4(%rbp)
cmpl $0x0, -0x1c4(%rbp)
jge 0x10b2e
movslq -0x1dc(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x1d8(%rbp)
jmp 0x10bf6
movq -0x190(%rbp), %rax
cmpq -0xd8(%rbp), %rax
je 0x10b4a
movl $0x1, -0x110(%rbp)
jmp 0x10b54
movl $0x3, -0x110(%rbp)
cmpl $0x0, -0x1dc(%rbp)
jle 0x10bc6
leaq -0x70(%rbp), %rax
movq %rax, -0x238(%rbp)
movslq -0x1dc(%rbp), %rdi
testq %rdi, %rdi
movq $-0x1, %rax
cmovsq %rax, %rdi
callq 0x6030
movq %rax, -0x230(%rbp)
jmp 0x10b8b
movq -0x230(%rbp), %rsi
movq -0x238(%rbp), %rdi
callq 0x10c20
jmp 0x10ba0
leaq -0x130(%rbp), %rdi
addq $0xc0, %rdi
callq 0xf430
movq %rax, %rdi
movq -0x20(%rbp), %rsi
movslq -0x1dc(%rbp), %rdx
callq 0x6450
jmp 0x10bc8
movq -0x1f8(%rbp), %rdi
addq $0x78, %rdi
leaq -0x130(%rbp), %rsi
callq 0x13df0
jmp 0x10be1
movslq -0x1dc(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x1d8(%rbp)
leaq -0x130(%rbp), %rdi
callq 0xbf60
movq -0x8(%rbp), %rax
addq $0x240, %rsp            # imm = 0x240
popq %rbp
retq
movq -0x1d0(%rbp), %rdi
callq 0x68a0
nopl (%rax,%rax)