uint32_t in_length = state->in_length;
uint64_t in_offset = state->in_offset;
files_struct *fsp = state->fsp;
+ const DATA_BLOB *hdr = state->smb2req->queue_entry.sendfile_header;
ssize_t nread;
+ ssize_t ret;
nread = SMB_VFS_SENDFILE(fsp->conn->sconn->sock,
fsp,
- state->smb2req->queue_entry.sendfile_header,
+ hdr,
in_offset,
in_length);
DEBUG(10,("smb2_sendfile_send_data: SMB_VFS_SENDFILE returned %d on file %s\n",
fsp_str_dbg(fsp) ));
if (nread == -1) {
- if (errno == ENOSYS || errno == EINTR) {
+ /*
+ * Returning ENOSYS means no data at all was sent.
+ Do this as a normal read. */
+ if (errno == ENOSYS) {
+ goto normal_read;
+ }
+
+ if (errno == EINTR) {
/*
- * Special hack for broken systems with no working
- * sendfile. Fake this up by doing read/write calls.
- */
+ * Special hack for broken Linux with no working sendfile. If we
+ * return EINTR we sent the header but not the rest of the data.
+ * Fake this up by doing read/write calls.
+ */
set_use_sendfile(SNUM(fsp->conn), false);
nread = fake_sendfile(fsp, in_offset, in_length);
if (nread == -1) {
DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
"falling back to the normal read: %s\n",
fsp_str_dbg(fsp)));
+ goto normal_read;
+ }
- nread = fake_sendfile(fsp, in_offset, in_length);
- if (nread == -1) {
- DEBUG(0,("smb2_sendfile_send_data: "
- "fake_sendfile failed for file "
- "%s (%s). Terminating\n",
- fsp_str_dbg(fsp),
- strerror(errno)));
- exit_server_cleanly("smb2_sendfile_send_data: "
- "fake_sendfile failed");
- }
+ /*
+ * We got a short read
+ */
+ goto out;
+
+normal_read:
+ /* Send out the header. */
+ ret = write_data(fsp->conn->sconn->sock,
+ (const char *)hdr->data, hdr->length);
+ if (ret != hdr->length) {
+ char addr[INET6_ADDRSTRLEN];
+ /*
+ * Try and give an error message saying what
+ * client failed.
+ */
+ DEBUG(0, ("smb2_sendfile_send_data: write_data failed "
+ "for client %s. Error %s\n",
+ get_peer_addr(fsp->conn->sconn->sock, addr,
+ sizeof(addr)),
+ strerror(errno)));
+
+ DEBUG(0,("smb2_sendfile_send_data: write_data failed for file "
+ "%s (%s). Terminating\n", fsp_str_dbg(fsp),
+ strerror(errno)));
+ exit_server_cleanly("smb2_sendfile_send_data: write_data failed");
+ }
+ nread = fake_sendfile(fsp, in_offset, in_length);
+ if (nread == -1) {
+ DEBUG(0,("smb2_sendfile_send_data: "
+ "fake_sendfile failed for file "
+ "%s (%s). Terminating\n",
+ fsp_str_dbg(fsp),
+ strerror(errno)));
+ exit_server_cleanly("smb2_sendfile_send_data: "
+ "fake_sendfile failed");
}
out:
if (nread < in_length) {
- sendfile_short_send(fsp, nread, 0, in_length);
+ sendfile_short_send(fsp, nread, hdr->length, in_length);
}
init_strict_lock_struct(fsp,