2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - read
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "vfs_posix.h"
24 #include "lib/events/events.h"
29 NTSTATUS
pvfs_read(struct ntvfs_module_context
*ntvfs
,
30 struct ntvfs_request
*req
, union smb_read
*rd
)
32 struct pvfs_state
*pvfs
= talloc_get_type(ntvfs
->private_data
,
40 if (rd
->generic
.level
!= RAW_READ_READX
) {
41 return ntvfs_map_read(ntvfs
, req
, rd
);
44 f
= pvfs_find_fd(pvfs
, req
, rd
->readx
.in
.file
.ntvfs
);
46 return NT_STATUS_INVALID_HANDLE
;
49 if (f
->handle
->fd
== -1) {
50 return NT_STATUS_INVALID_DEVICE_REQUEST
;
53 mask
= SEC_FILE_READ_DATA
;
54 if (rd
->readx
.in
.read_for_execute
) {
55 mask
|= SEC_FILE_EXECUTE
;
57 if (!(f
->access_mask
& mask
)) {
58 return NT_STATUS_ACCESS_DENIED
;
61 maxcnt
= rd
->readx
.in
.maxcnt
;
62 if (maxcnt
> 2*UINT16_MAX
&& req
->ctx
->protocol
< PROTOCOL_SMB2_02
) {
63 DEBUG(3,(__location__
": Invalid SMB maxcnt 0x%x\n", maxcnt
));
64 return NT_STATUS_INVALID_PARAMETER
;
67 status
= pvfs_check_lock(pvfs
, f
, req
->smbpid
,
71 if (!NT_STATUS_IS_OK(status
)) {
75 if (f
->handle
->name
->stream_name
) {
76 ret
= pvfs_stream_read(pvfs
, f
->handle
,
77 rd
->readx
.out
.data
, maxcnt
, rd
->readx
.in
.offset
);
80 /* possibly try an aio read */
81 if ((req
->async_states
->state
& NTVFS_ASYNC_STATE_MAY_ASYNC
) &&
82 (pvfs
->flags
& PVFS_FLAG_LINUX_AIO
)) {
83 status
= pvfs_aio_pread(req
, rd
, f
, maxcnt
);
84 if (NT_STATUS_IS_OK(status
)) {
89 ret
= pread(f
->handle
->fd
,
95 return pvfs_map_errno(pvfs
, errno
);
98 /* only SMB2 honors mincnt */
99 if (req
->ctx
->protocol
>= PROTOCOL_SMB2_02
) {
100 if (rd
->readx
.in
.mincnt
> ret
||
101 (ret
== 0 && maxcnt
> 0)) {
102 return NT_STATUS_END_OF_FILE
;
106 f
->handle
->position
= f
->handle
->seek_offset
= rd
->readx
.in
.offset
+ ret
;
108 rd
->readx
.out
.nread
= ret
;
109 rd
->readx
.out
.remaining
= 0xFFFF;
110 rd
->readx
.out
.compaction_mode
= 0;