コード例 #1
0
ファイル: spillbuf-test.c プロジェクト: gunjanms/svnmigration
static svn_error_t *
test_spillbuf__interleaving(apr_pool_t *pool, svn_spillbuf_t* buf)
{
  SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
  /* now: two blocks: 8 and 4 bytes  */

  CHECK_READ(buf, 12, "abcdefgh", pool);
  /* now: one block: 4 bytes  */

  SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
  /* now: two blocks: 8 and 2 bytes  */

  CHECK_READ(buf, 10, "ijklmnop", pool);
  /* now: one block: 2 bytes  */

  SVN_ERR(svn_spillbuf__write(buf, "stuvwx", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ABCDEF", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "GHIJKL", 6, pool));
  /* now: two blocks: 8 and 6 bytes, and 6 bytes spilled to a file  */

  CHECK_READ(buf, 20, "qrstuvwx", pool);
  CHECK_READ(buf, 12, "ABCDEF", pool);
  CHECK_READ(buf, 6, "GHIJKL", pool);

  SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);

  return SVN_NO_ERROR;
}
コード例 #2
0
ファイル: spillbuf-test.c プロジェクト: gunjanms/svnmigration
static svn_error_t *
test_spillbuf__basic(apr_pool_t *pool, apr_size_t len, svn_spillbuf_t *buf)
{
  int i;
  const char *readptr;
  apr_size_t readlen;

  /* It starts empty.  */
  SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);

  /* Place enough data into the buffer to cause a spill to disk.  */
  for (i = 20; i--; )
    SVN_ERR(svn_spillbuf__write(buf, basic_data, len, pool));

  /* And now has content.  */
  SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) > 0);

  /* Verify that we can read 20 copies of basic_data from the buffer.  */
  for (i = 20; i--; )
    CHECK_READ(buf, (i + 1) * len, basic_data, pool);

  /* And after precisely 20 reads, it should be empty.  */
  SVN_ERR(svn_spillbuf__read(&readptr, &readlen, buf, pool));
  SVN_TEST_ASSERT(readptr == NULL);
  SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);

  return SVN_NO_ERROR;
}
コード例 #3
0
ファイル: spillbuf-test.c プロジェクト: gunjanms/svnmigration
static svn_error_t *
test_spillbuf__rwfile(apr_pool_t *pool, svn_spillbuf_t *buf)
{
  SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
  /* now: two blocks: 4 and 2 bytes, and 12 bytes in spill file.  */

  CHECK_READ(buf, 18, "abcd", pool);
  /* now: one block: 2 bytes, and 12 bytes in spill file.  */

  CHECK_READ(buf, 14, "ef", pool);
  /* now: no blocks, and 12 bytes in spill file.  */

  CHECK_READ(buf, 12, "ghij", pool);
  /* now: no blocks, and 8 bytes in spill file.  */

  /* Write more data. It should be appended to the spill file.  */
  SVN_ERR(svn_spillbuf__write(buf, "stuvwx", 6, pool));
  /* now: no blocks, and 14 bytes in spill file.  */

  CHECK_READ(buf, 14, "klmn", pool);
  /* now: no blocks, and 10 bytes in spill file.  */

  CHECK_READ(buf, 10, "opqr", pool);
  /* now: no blocks, and 6 bytes in spill file.  */

  CHECK_READ(buf, 6, "stuv", pool);
  /* now: no blocks, and 2 bytes in spill file.  */

  CHECK_READ(buf, 2, "wx", pool);
  /* now: no blocks, and no spill file.  */

  return SVN_NO_ERROR;
}
コード例 #4
0
ファイル: WASMReader.cpp プロジェクト: capn-ace/webkit
bool WASMReader::readFloat(float& result)
{
    CHECK_READ(4);
    union {
        uint8_t bytes[4];
        float floatValue;
    } u = {
#if CPU(BIG_ENDIAN)
        { m_cursor[3], m_cursor[2], m_cursor[1], m_cursor[0] }
#else
        { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3] }
#endif
    };
コード例 #5
0
ファイル: Array.cpp プロジェクト: pybus/pybus
Ref<Object> Type::Array::read(PyPP__ARGS){
	WRef<Message> msg;
	PyPP__ARG_PARSE(1, arg("message"_py, msg));

	auto res=PyPP::List::new_(0);
	Ref<Object> func=of->py_getattr("read"_py);

	CHECK_READ(sd_bus_message_enter_container)(msg->handle, 'a', of->signature);

	while(true){
		if(CHECK(sd_bus_message_at_end)(msg->handle, 0)) break;
		auto next=func->py_callv(msg);
		res->list_append(next);
	}

	CHECK(sd_bus_message_exit_container)(msg->handle);
	return res;
}
コード例 #6
0
ファイル: spillbuf-test.c プロジェクト: gunjanms/svnmigration
static svn_error_t *
test_spillbuf__eof(apr_pool_t *pool, svn_spillbuf_t *buf)
{
  SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
  /* now: two blocks: 4 and 2 bytes, and 6 bytes in spill file.  */

  CHECK_READ(buf, 12, "abcd", pool);
  CHECK_READ(buf, 8, "ef", pool);
  CHECK_READ(buf, 6, "ghij", pool);
  CHECK_READ(buf, 2, "kl", pool);
  /* The spill file should have been emptied and forgotten.  */

  /* Assuming the spill file has been forgotten, this should result in
     precisely the same behavior. Specifically: the initial write should
     create two blocks, and the second write should be spilled. If there
     *was* a spill file, then this written data would go into the file.  */
  SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
  CHECK_READ(buf, 12, "abcd", pool);
  CHECK_READ(buf, 8, "ef", pool);
  CHECK_READ(buf, 6, "ghij", pool);
  CHECK_READ(buf, 2, "kl", pool);
  /* The spill file should have been emptied and forgotten.  */

  /* Now, let's do a sequence where we arrange to hit EOF precisely on
     a block-sized read. Note: the second write must be more than 4 bytes,
     or it will not cause a spill. We use 8 to get the right boundary.  */
  SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ghijklmn", 8, pool));
  CHECK_READ(buf, 14, "abcd", pool);
  CHECK_READ(buf, 10, "ef", pool);
  CHECK_READ(buf, 8, "ghij", pool);
  CHECK_READ(buf, 4, "klmn", pool);
  /* We discard the spill file when we know it has no data, rather than
     upon hitting EOF (upon a read attempt). Thus, the spill file should
     be gone.  */

  /* Verify the forgotten spill file.  */
  SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
  SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
  CHECK_READ(buf, 12, "abcd", pool);
  CHECK_READ(buf, 8, "ef", pool);
  CHECK_READ(buf, 6, "ghij", pool);
  /* Two unread bytes remaining in the spill file.  */
  SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 2);

  return SVN_NO_ERROR;
}
コード例 #7
0
static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
					      struct tevent_context *ev,
					      struct smbd_smb2_request *smb2req,
					      uint32_t in_smbpid,
					      uint64_t in_file_id_volatile,
					      uint32_t in_length,
					      uint64_t in_offset,
					      uint32_t in_minimum,
					      uint32_t in_remaining)
{
	NTSTATUS status;
	struct tevent_req *req = NULL;
	struct smbd_smb2_read_state *state = NULL;
	struct smb_request *smbreq = NULL;
	connection_struct *conn = smb2req->tcon->compat_conn;
	files_struct *fsp = NULL;
	ssize_t nread = -1;
	struct lock_struct lock;
	int saved_errno;

	req = tevent_req_create(mem_ctx, &state,
				struct smbd_smb2_read_state);
	if (req == NULL) {
		return NULL;
	}
	state->smb2req = smb2req;
	state->in_length = in_length;
	state->in_offset = in_offset;
	state->in_minimum = in_minimum;
	state->out_data = data_blob_null;
	state->out_remaining = 0;

	DEBUG(10,("smbd_smb2_read: file_id[0x%016llX]\n",
		  (unsigned long long)in_file_id_volatile));

	smbreq = smbd_smb2_fake_smb_request(smb2req);
	if (tevent_req_nomem(smbreq, req)) {
		return tevent_req_post(req, ev);
	}

	fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
	if (fsp == NULL) {
		tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
		return tevent_req_post(req, ev);
	}
	if (conn != fsp->conn) {
		tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
		return tevent_req_post(req, ev);
	}
	if (smb2req->session->vuid != fsp->vuid) {
		tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
		return tevent_req_post(req, ev);
	}
	if (fsp->is_directory) {
		tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
		return tevent_req_post(req, ev);
	}

	state->fsp = fsp;
	state->in_file_id_volatile = in_file_id_volatile;

	if (IS_IPC(smbreq->conn)) {
		struct tevent_req *subreq = NULL;

		state->out_data = data_blob_talloc(state, NULL, in_length);
		if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
			return tevent_req_post(req, ev);
		}

		if (!fsp_is_np(fsp)) {
			tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
			return tevent_req_post(req, ev);
		}

		subreq = np_read_send(state, server_event_context(),
				      fsp->fake_file_handle,
				      state->out_data.data,
				      state->out_data.length);
		if (tevent_req_nomem(subreq, req)) {
			return tevent_req_post(req, ev);
		}
		tevent_req_set_callback(subreq,
					smbd_smb2_read_pipe_done,
					req);
		return req;
	}

	if (!CHECK_READ(fsp, smbreq)) {
		tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
		return tevent_req_post(req, ev);
	}

	status = schedule_smb2_aio_read(fsp->conn,
				smbreq,
				fsp,
				state,
				&state->out_data,
				(SMB_OFF_T)in_offset,
				(size_t)in_length);

	if (NT_STATUS_IS_OK(status)) {
		/*
		 * Doing an async read. Don't
		 * send a "gone async" message
		 * as we expect this to be less
		 * than the client timeout period.
		 * JRA. FIXME for offline files..
		 * FIXME. Add cancel code..
		 */
		smb2req->async = true;
		return req;
	}

	if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
		/* Real error in setting up aio. Fail. */
		tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
		return tevent_req_post(req, ev);
	}

	/* Fallback to synchronous. */

	init_strict_lock_struct(fsp,
				in_file_id_volatile,
				in_offset,
				in_length,
				READ_LOCK,
				&lock);

	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
		tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
		return tevent_req_post(req, ev);
	}

	/* Try sendfile in preference. */
	status = schedule_smb2_sendfile_read(smb2req, state);
	if (NT_STATUS_IS_OK(status)) {
		tevent_req_done(req);
		return tevent_req_post(req, ev);
	} else {
		if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
			SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
			tevent_req_nterror(req, status);
			return tevent_req_post(req, ev);
		}
	}

	/* Ok, read into memory. Allocate the out buffer. */
	state->out_data = data_blob_talloc(state, NULL, in_length);
	if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
		SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
		return tevent_req_post(req, ev);
	}

	nread = read_file(fsp,
			  (char *)state->out_data.data,
			  in_offset,
			  in_length);

	saved_errno = errno;

	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);

	DEBUG(10,("smbd_smb2_read: file %s handle [0x%016llX] offset=%llu "
		"len=%llu returned %lld\n",
		fsp_str_dbg(fsp),
		(unsigned long long)in_file_id_volatile,
		(unsigned long long)in_offset,
		(unsigned long long)in_length,
		(long long)nread));

	status = smb2_read_complete(req, nread, saved_errno);
	if (!NT_STATUS_IS_OK(status)) {
		tevent_req_nterror(req, status);
	} else {
		/* Success. */
		tevent_req_done(req);
	}
	return tevent_req_post(req, ev);
}
コード例 #8
0
ファイル: sector.c プロジェクト: Aishou/lxdream
cdrom_error_t sector_source_read_sectors( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, cdrom_read_mode_t mode,
                                          unsigned char *buf, size_t *length )
{
    CHECK_READ(device,lba,block_count);
    return device->read_sectors(device, lba, block_count, mode, buf, length);
}
コード例 #9
0
ファイル: sector.c プロジェクト: Aishou/lxdream
/********************* Public functions *************************/
cdrom_error_t sector_source_read( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
{
    CHECK_READ(device,lba,block_count);
    return device->read_blocks(device, lba, block_count, buf);
}
コード例 #10
0
ファイル: bmp.cpp プロジェクト: gatgui/gimg
GCORE_MODULE_API gimg::Image* readImage(const char *filepath) {
  // dib is not in the format we want 
  // PF_RGB | PF_RGBA (24 or 32 bits)
  // -> NOT BGR beware !
  
  gimg::Image *bmp = 0;
  
  BITMAPFILEHEADER bf;
  BITMAPINFOHEADER bi;
  
  memset(&bf, 0, BF_SIZE);
  memset(&bi, 0, BI_SIZE);
  
  FILE *bitmap = fopen(filepath, "rb");
  
  if (bitmap) {
    
    // Read file header and check
    CHECK_READ(&(bf.bfType), WORD, bitmap, "type");
    if (bf.bfType != BM) {
      std::cerr << "Un-supported BMP type" << std::endl;
      return 0;
    }
    CHECK_READ(&(bf.bfSize), DWORD, bitmap, "header size");
    CHECK_READ(&(bf.bfReserved1), WORD, bitmap, "reserved1");
    CHECK_READ(&(bf.bfReserved2), WORD, bitmap, "reserved2");
    CHECK_READ(&(bf.bfOffBits), DWORD, bitmap, "data offset");
    
    // Read info header and check
    CHECK_READ(&(bi.biSize), DWORD, bitmap, "info size");
    if (bi.biSize <= sizeof(BITMAPCOREHEADER)) {
      std::cerr << "BMP file format not supported" << std::endl;
    }
    CHECK_READ(&(bi.biWidth), LONG, bitmap, "width");
    CHECK_READ(&(bi.biHeight), LONG, bitmap, "height");
    CHECK_READ(&(bi.biPlanes), WORD, bitmap, "planes");
    CHECK_READ(&(bi.biBitCount), WORD, bitmap, "bpp");
    if (bi.biBitCount < 24) {
      std::cerr << "BMP file format not supported, expected 24/32 bits color type" << std::endl;
      return 0;
    }
#ifdef _DEBUG
    std::cout << "BMP: " << bi.biWidth << "x" << bi.biHeight << ":" << bi.biBitCount << std::endl;
#endif
    CHECK_READ(&(bi.biCompression), DWORD, bitmap, "compression");
    if (bi.biCompression > BI_RGB) {
      std::cerr << "BMP file format not supported, expected non-compressed data" << std::endl;
      return 0;
    }
    CHECK_READ(&(bi.biSizeImage), DWORD, bitmap, "data size");
    CHECK_READ(&(bi.biXPelsPerMeter), LONG, bitmap, "x units");
    CHECK_READ(&(bi.biYPelsPerMeter), LONG, bitmap, "y units");
    CHECK_READ(&(bi.biClrUsed), DWORD, bitmap, "used color count");
    if (bi.biClrUsed > 0) {
      std::cerr << "Indexed color BMP files not suppored" << std::endl;
      return 0;
    }
    CHECK_READ(&(bi.biClrImportant), DWORD, bitmap, "important color count");
    
    // beware bi.biHeight could be < 0 -> origin top left
    bool hflip = false;
    if (bi.biHeight < 0) {
      hflip = true;
      bi.biHeight = -bi.biHeight;
    }
    
    // pitch is not just BytesPerPixel * W
    // in bitmap file, scanline byte size is adjusted to nearest multiple of 4 size
    // the " >> 3" is to convert bit size to byte size
    // +31 is to make sure we will not reduce the width when rounding up
    // ~31 clear the last 5 bits (summing to 31) in order to make size a multiple of 32
    
    unsigned long pitch = (((bi.biWidth * bi.biBitCount) + 31) & ~31) >> 3;
    
    unsigned long imgsz = bi.biSizeImage;
    
#ifdef _DEBUG
    std::cout << "gimg::Image picth: " << (bi.biWidth * 3) << std::endl;
    std::cout << "BMP image picth: " << pitch << std::endl;
#endif
    
    if (imgsz == 0) {
      imgsz = pitch * bi.biHeight;
    }
    
    void *dib = malloc(imgsz);
    if (!dib) {
      std::cerr << "Could not allocate memory to read BMP file data" << std::endl;
      return 0;
    }
    
    if (bf.bfOffBits != 0) {
#ifdef _DEBUG
      std::cout << "BMP file offset set: " << bf.bfOffBits << std::endl;
#endif
      fseek(bitmap, bf.bfOffBits, SEEK_SET);
    }
    
    if (fread(dib, 1, imgsz, bitmap) != imgsz) {
      free(dib);
      std::cerr << "Could not read BMP file data" << std::endl;
      return 0;
    }
    
    // now copy scanlines and we are done, use RGBQUAD because bitmap are store in BGR format
    // there absolutely no alpha in bitmap (even on 32 mode ?)
    // should be pretty easy from here
    
    gimg::PixelDesc desc(gimg::PF_RGB, gimg::PT_INT_8);
    
    bmp = new gimg::Image(desc, bi.biWidth, bi.biHeight);
    
    size_t srcPixSize = bi.biBitCount >> 3;
    
    void *dstPixels = bmp->getPixels();
    size_t dstPitch = bi.biWidth * desc.getBytesPerPixel();
    
#ifdef _DEBUG
    std::cout << "gimg::Image pitch (from PixelDesc): " << dstPitch << std::endl;
#endif
    
    for (LONG y=0; y<bi.biHeight; ++y) {
    
      // top rows coming first
      unsigned char* dibScanline = (unsigned char*)dib + (((bi.biHeight - 1) - y) * pitch);
      
      unsigned char* bmpScanline = ((unsigned char*)dstPixels) + (y * dstPitch);
      
      for (LONG x=0; x<bi.biWidth; ++x) {
        
        bmpScanline[3*x+0] = dibScanline[2];
        bmpScanline[3*x+1] = dibScanline[1];
        bmpScanline[3*x+2] = dibScanline[0];
        
        dibScanline += srcPixSize;
      }
    }
    
    free(dib);
    
    fclose(bitmap);
  }
  
#ifdef _DEBUG
  std::cout << "Image read successfully !" << std::endl;
#endif
  
  return bmp;
}
コード例 #11
0
static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
					      struct tevent_context *ev,
					      struct smbd_smb2_request *smb2req,
					      struct files_struct *fsp,
					      uint32_t in_length,
					      uint64_t in_offset,
					      uint32_t in_minimum,
					      uint32_t in_remaining)
{
	NTSTATUS status;
	struct tevent_req *req = NULL;
	struct smbd_smb2_read_state *state = NULL;
	struct smb_request *smbreq = NULL;
	connection_struct *conn = smb2req->tcon->compat;
	ssize_t nread = -1;
	struct lock_struct lock;
	int saved_errno;

	req = tevent_req_create(mem_ctx, &state,
				struct smbd_smb2_read_state);
	if (req == NULL) {
		return NULL;
	}
	state->smb2req = smb2req;
	state->in_length = in_length;
	state->in_offset = in_offset;
	state->in_minimum = in_minimum;
	state->out_data = data_blob_null;
	state->out_remaining = 0;

	DEBUG(10,("smbd_smb2_read: %s - %s\n",
		  fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));

	smbreq = smbd_smb2_fake_smb_request(smb2req);
	if (tevent_req_nomem(smbreq, req)) {
		return tevent_req_post(req, ev);
	}
	state->smbreq = smbreq;

	if (fsp->is_directory) {
		tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
		return tevent_req_post(req, ev);
	}

	state->fsp = fsp;

	if (IS_IPC(smbreq->conn)) {
		struct tevent_req *subreq = NULL;

		state->out_data = data_blob_talloc(state, NULL, in_length);
		if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
			return tevent_req_post(req, ev);
		}

		if (!fsp_is_np(fsp)) {
			tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
			return tevent_req_post(req, ev);
		}

		subreq = np_read_send(state, ev,
				      fsp->fake_file_handle,
				      state->out_data.data,
				      state->out_data.length);
		if (tevent_req_nomem(subreq, req)) {
			return tevent_req_post(req, ev);
		}
		tevent_req_set_callback(subreq,
					smbd_smb2_read_pipe_done,
					req);
		return req;
	}

	if (!CHECK_READ(fsp, smbreq)) {
		tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
		return tevent_req_post(req, ev);
	}

	status = schedule_smb2_aio_read(fsp->conn,
				smbreq,
				fsp,
				state,
				&state->out_data,
				(off_t)in_offset,
				(size_t)in_length);

	if (NT_STATUS_IS_OK(status)) {
		/*
		 * Doing an async read, allow this
		 * request to be canceled
		 */
		tevent_req_set_cancel_fn(req, smbd_smb2_read_cancel);
		return req;
	}

	if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
		/* Real error in setting up aio. Fail. */
		tevent_req_nterror(req, status);
		return tevent_req_post(req, ev);
	}

	/* Fallback to synchronous. */

	init_strict_lock_struct(fsp,
				fsp->op->global->open_persistent_id,
				in_offset,
				in_length,
				READ_LOCK,
				&lock);

	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
		tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
		return tevent_req_post(req, ev);
	}

	/* Try sendfile in preference. */
	status = schedule_smb2_sendfile_read(smb2req, state);
	if (NT_STATUS_IS_OK(status)) {
		tevent_req_done(req);
		return tevent_req_post(req, ev);
	} else {
		if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
			SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
			tevent_req_nterror(req, status);
			return tevent_req_post(req, ev);
		}
	}

	/* Ok, read into memory. Allocate the out buffer. */
	state->out_data = data_blob_talloc(state, NULL, in_length);
	if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
		SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
		return tevent_req_post(req, ev);
	}

	nread = read_file(fsp,
			  (char *)state->out_data.data,
			  in_offset,
			  in_length);

	saved_errno = errno;

	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);

	DEBUG(10,("smbd_smb2_read: file %s, %s, offset=%llu "
		"len=%llu returned %lld\n",
		fsp_str_dbg(fsp),
		fsp_fnum_dbg(fsp),
		(unsigned long long)in_offset,
		(unsigned long long)in_length,
		(long long)nread));

	status = smb2_read_complete(req, nread, saved_errno);
	if (!NT_STATUS_IS_OK(status)) {
		tevent_req_nterror(req, status);
	} else {
		/* Success. */
		tevent_req_done(req);
	}
	return tevent_req_post(req, ev);
}