2 Unix SMB/Netbios implementation.
4 read/write to a files_struct
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Jeremy Allison 2000-2002. - write cache.
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/>.
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "smbprofile.h"
28 /****************************************************************************
30 ****************************************************************************/
32 ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n)
36 /* you can't read from print files */
37 if (fsp->print_file) {
45 ret = SMB_VFS_PREAD(fsp,data,n,pos);
52 DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
53 fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
56 fsp->fh->position_information = fsp->fh->pos;
61 /****************************************************************************
62 *Really* write to a file.
63 ****************************************************************************/
65 static ssize_t real_write_file(struct smb_request *req,
74 if (pos && lp_strict_allocate(SNUM(fsp->conn) &&
76 if (vfs_fill_sparse(fsp, pos) == -1) {
80 ret = vfs_pwrite_data(req, fsp, data, n, pos);
82 DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
83 fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
88 /* Yes - this is correct - writes don't update this. JRA. */
89 /* Found by Samba4 tests. */
91 fsp->position_information = fsp->pos;
98 void fsp_flush_write_time_update(struct files_struct *fsp)
101 * Note this won't expect any impersonation!
102 * So don't call any SMB_VFS operations here!
105 DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp)));
107 /* change the write time in the open file db. */
108 (void)set_write_time(fsp->file_id, timespec_current());
111 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
112 FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name);
114 /* Remove the timed event handler. */
115 TALLOC_FREE(fsp->update_write_time_event);
118 static void update_write_time_handler(struct tevent_context *ctx,
119 struct tevent_timer *te,
123 files_struct *fsp = (files_struct *)private_data;
124 fsp_flush_write_time_update(fsp);
127 /*********************************************************
128 Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
130 *********************************************************/
132 void trigger_write_time_update(struct files_struct *fsp)
136 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
137 /* Don't use delayed writes on POSIX files. */
141 if (fsp->write_time_forced) {
142 /* No point - "sticky" write times
148 /* We need to remember someone did a write
149 * and update to current time on close. */
151 fsp->update_write_time_on_close = true;
153 if (fsp->update_write_time_triggered) {
155 * We only update the write time after 2 seconds
156 * on the first normal write. After that
157 * no other writes affect this until close.
161 fsp->update_write_time_triggered = true;
163 delay = lp_parm_int(SNUM(fsp->conn),
164 "smbd", "writetimeupdatedelay",
165 WRITE_TIME_UPDATE_USEC_DELAY);
167 DEBUG(5, ("Update write time %d usec later on %s\n",
168 delay, fsp_str_dbg(fsp)));
170 /* trigger the update 2 seconds later */
171 fsp->update_write_time_event =
172 tevent_add_timer(fsp->conn->sconn->ev_ctx, NULL,
173 timeval_current_ofs_usec(delay),
174 update_write_time_handler, fsp);
177 void trigger_write_time_update_immediate(struct files_struct *fsp)
179 struct smb_file_time ft;
181 init_smb_file_time(&ft);
183 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
184 /* Don't use delayed writes on POSIX files. */
188 if (fsp->write_time_forced) {
190 * No point - "sticky" write times
196 TALLOC_FREE(fsp->update_write_time_event);
197 DEBUG(5, ("Update write time immediate on %s\n",
200 /* After an immediate update, reset the trigger. */
201 fsp->update_write_time_triggered = true;
202 fsp->update_write_time_on_close = false;
204 ft.mtime = timespec_current();
206 /* Update the time in the open file db. */
207 (void)set_write_time(fsp->file_id, ft.mtime);
209 /* Now set on disk - takes care of notify. */
210 (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
213 void mark_file_modified(files_struct *fsp)
217 trigger_write_time_update(fsp);
223 fsp->modified = true;
225 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
228 if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
229 MAP_ARCHIVE(fsp->conn))) {
233 dosmode = dos_mode(fsp->conn, fsp->fsp_name);
234 if (IS_DOS_ARCHIVE(dosmode)) {
237 file_set_dosmode(fsp->conn, fsp->fsp_name,
238 dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false);
241 /****************************************************************************
243 ****************************************************************************/
245 ssize_t write_file(struct smb_request *req,
251 ssize_t total_written = 0;
253 if (fsp->print_file) {
257 ret = print_spool_write(fsp, data, n, pos, &t);
265 if (!fsp->can_write) {
270 mark_file_modified(fsp);
273 * If this file is level II oplocked then we need
274 * to grab the shared memory lock and inform all
275 * other files with a level II lock that they need
276 * to flush their read caches. We keep the lock over
277 * the shared memory area whilst doing this.
280 /* This should actually be improved to span the write. */
281 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
282 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
284 total_written = real_write_file(req, fsp, data, pos, n);
285 return total_written;
288 /*******************************************************************
290 ********************************************************************/
292 NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through)
294 if (fsp->fh->fd == -1)
295 return NT_STATUS_INVALID_HANDLE;
297 if (lp_strict_sync(SNUM(conn)) &&
298 (lp_sync_always(SNUM(conn)) || write_through)) {
300 ret = smb_vfs_fsync_sync(fsp);
302 return map_nt_error_from_unix(errno);