2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - write
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 "librpc/gen_ndr/security.h"
25 #include "lib/events/events.h"
27 static void pvfs_write_time_update_handler(struct tevent_context
*ev
,
28 struct tevent_timer
*te
,
32 struct pvfs_file_handle
*h
= talloc_get_type(private_data
,
33 struct pvfs_file_handle
);
38 lck
= odb_lock(h
, h
->pvfs
->odb_context
, &h
->odb_locking_key
);
40 DEBUG(0,("Unable to lock opendb for write time update\n"));
44 write_time
= timeval_to_nttime(&tv
);
46 status
= odb_set_write_time(lck
, write_time
, false);
47 if (!NT_STATUS_IS_OK(status
)) {
48 DEBUG(0,("Unable to update write time: %s\n",
55 h
->write_time
.update_event
= NULL
;
58 static void pvfs_trigger_write_time_update(struct pvfs_file_handle
*h
)
60 struct pvfs_state
*pvfs
= h
->pvfs
;
63 if (h
->write_time
.update_triggered
) {
67 tv
= timeval_current_ofs_usec(pvfs
->writetime_delay
);
69 h
->write_time
.update_triggered
= true;
70 h
->write_time
.update_on_close
= true;
71 h
->write_time
.update_event
= tevent_add_timer(pvfs
->ntvfs
->ctx
->event_ctx
,
73 pvfs_write_time_update_handler
,
75 if (!h
->write_time
.update_event
) {
76 DEBUG(0,("Failed tevent_add_timer\n"));
83 NTSTATUS
pvfs_write(struct ntvfs_module_context
*ntvfs
,
84 struct ntvfs_request
*req
, union smb_write
*wr
)
86 struct pvfs_state
*pvfs
= talloc_get_type(ntvfs
->private_data
,
92 if (wr
->generic
.level
!= RAW_WRITE_WRITEX
) {
93 return ntvfs_map_write(ntvfs
, req
, wr
);
96 f
= pvfs_find_fd(pvfs
, req
, wr
->writex
.in
.file
.ntvfs
);
98 return NT_STATUS_INVALID_HANDLE
;
101 if (f
->handle
->fd
== -1) {
102 return NT_STATUS_INVALID_DEVICE_REQUEST
;
105 if (!(f
->access_mask
& (SEC_FILE_WRITE_DATA
| SEC_FILE_APPEND_DATA
))) {
106 return NT_STATUS_ACCESS_DENIED
;
109 status
= pvfs_check_lock(pvfs
, f
, req
->smbpid
,
110 wr
->writex
.in
.offset
,
113 NT_STATUS_NOT_OK_RETURN(status
);
115 status
= pvfs_break_level2_oplocks(f
);
116 NT_STATUS_NOT_OK_RETURN(status
);
118 pvfs_trigger_write_time_update(f
->handle
);
120 if (f
->handle
->name
->stream_name
) {
121 ret
= pvfs_stream_write(pvfs
,
125 wr
->writex
.in
.offset
);
128 /* possibly try an aio write */
129 if ((req
->async_states
->state
& NTVFS_ASYNC_STATE_MAY_ASYNC
) &&
130 (pvfs
->flags
& PVFS_FLAG_LINUX_AIO
)) {
131 status
= pvfs_aio_pwrite(req
, wr
, f
);
132 if (NT_STATUS_IS_OK(status
)) {
137 ret
= pwrite(f
->handle
->fd
,
140 wr
->writex
.in
.offset
);
143 if (errno
== EFBIG
) {
144 return NT_STATUS_INVALID_PARAMETER
;
146 return pvfs_map_errno(pvfs
, errno
);
149 f
->handle
->seek_offset
= wr
->writex
.in
.offset
+ ret
;
151 wr
->writex
.out
.nwritten
= ret
;
152 wr
->writex
.out
.remaining
= 0; /* should fill this in? */