Copy an AFF4 object that supports a read interface to local filesystem.

  Args:
    aff4_urn: URN of thing to copy.
    target_dir: Directory to copy the file to.
    token: Auth token.
    overwrite: If True overwrite the file if it exists.

  Returns:
    If aff4_urn points to a file, returns path to the downloaded file.
    Otherwise returns None.

  By default file will only be overwritten if file size differs.

def CopyAFF4ToLocal(aff4_urn, target_dir, token=None, overwrite=False):
  """Copy an AFF4 object that supports a read interface to local filesystem.

  Args:
    aff4_urn: URN of thing to copy.
    target_dir: Directory to copy the file to.
    token: Auth token.
    overwrite: If True overwrite the file if it exists.

  Returns:
    If aff4_urn points to a file, returns path to the downloaded file.
    Otherwise returns None.

  By default file will only be overwritten if file size differs.
  """
  try:
    fd = aff4.FACTORY.Open(aff4_urn, token=token)
    filepath = os.path.join(target_dir, fd.urn.Path()[1:])

    # If urn points to a directory, just create it.
    if isinstance(fd, standard.VFSDirectory):
      try:
        os.makedirs(filepath)
      except OSError:
        pass

      return None
    # If urn points to a file, download it.
    elif isinstance(fd, aff4.AFF4Stream):
      if not os.path.isfile(filepath):
        try:
          # Ensure directory exists.
          os.makedirs(os.path.dirname(filepath))
        except OSError:
          pass
        DownloadFile(fd, filepath)
      elif (os.stat(filepath)[stat.ST_SIZE] != fd.Get(fd.Schema.SIZE) or
            overwrite):
        # We should overwrite because user said, or file sizes differ.
        DownloadFile(fd, filepath)
      else:
        logging.info("File %s exists, skipping", filepath)

      return filepath
    else:
      raise ValueError("Opened urn is neither a downloaded file nor a "
                       "directory: %s" % aff4_urn)

  except IOError as e:
    logging.exception("Failed to read %s due to %s", aff4_urn, e)
    raise