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
)
38 /* you can't read from print files */
39 if (fsp
->print_file
) {
44 ok
= vfs_valid_pread_range(pos
, n
);
50 fh_set_pos(fsp
->fh
, pos
);
53 ret
= SMB_VFS_PREAD(fsp
,data
,n
,pos
);
60 DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
61 fsp_str_dbg(fsp
), (double)pos
, (unsigned long)n
, (long)ret
));
63 new_pos
= fh_get_pos(fsp
->fh
) + ret
;
64 fh_set_pos(fsp
->fh
, new_pos
);
65 fh_set_position_information(fsp
->fh
, new_pos
);
70 /****************************************************************************
71 *Really* write to a file.
72 ****************************************************************************/
74 static ssize_t
real_write_file(struct smb_request
*req
,
83 ok
= vfs_valid_pwrite_range(pos
, n
);
93 fh_set_pos(fsp
->fh
, pos
);
95 lp_strict_allocate(SNUM(fsp
->conn
)) &&
96 !fsp
->fsp_flags
.is_sparse
)
98 if (vfs_fill_sparse(fsp
, pos
) == -1) {
102 ret
= vfs_pwrite_data(req
, fsp
, data
, n
, pos
);
104 DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
105 fsp_str_dbg(fsp
), (double)pos
, (unsigned long)n
, (long)ret
));
108 off_t new_pos
= fh_get_pos(fsp
->fh
) + ret
;
109 fh_set_pos(fsp
->fh
, new_pos
);
111 /* Yes - this is correct - writes don't update this. JRA. */
112 /* Found by Samba4 tests. */
114 fsp
->position_information
= fsp
->pos
;
121 void fsp_flush_write_time_update(struct files_struct
*fsp
)
124 * Note this won't expect any impersonation!
125 * So don't call any SMB_VFS operations here!
128 DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp
)));
130 trigger_write_time_update_immediate(fsp
);
133 static void update_write_time_handler(struct tevent_context
*ctx
,
134 struct tevent_timer
*te
,
138 files_struct
*fsp
= (files_struct
*)private_data
;
139 fsp_flush_write_time_update(fsp
);
142 /*********************************************************
143 Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
145 *********************************************************/
147 void trigger_write_time_update(struct files_struct
*fsp
)
151 if (fsp
->fsp_flags
.posix_open
) {
152 /* Don't use delayed writes on POSIX files. */
156 if (fsp
->fsp_flags
.write_time_forced
) {
157 /* No point - "sticky" write times
163 /* We need to remember someone did a write
164 * and update to current time on close. */
166 fsp
->fsp_flags
.update_write_time_on_close
= true;
168 if (fsp
->fsp_flags
.update_write_time_triggered
) {
170 * We only update the write time after 2 seconds
171 * on the first normal write. After that
172 * no other writes affect this until close.
176 fsp
->fsp_flags
.update_write_time_triggered
= true;
178 delay
= lp_parm_int(SNUM(fsp
->conn
),
179 "smbd", "writetimeupdatedelay",
180 WRITE_TIME_UPDATE_USEC_DELAY
);
182 DEBUG(5, ("Update write time %d usec later on %s\n",
183 delay
, fsp_str_dbg(fsp
)));
185 /* trigger the update 2 seconds later */
186 fsp
->update_write_time_event
=
187 tevent_add_timer(fsp
->conn
->sconn
->ev_ctx
, NULL
,
188 timeval_current_ofs_usec(delay
),
189 update_write_time_handler
, fsp
);
192 void trigger_write_time_update_immediate(struct files_struct
*fsp
)
194 struct smb_file_time ft
;
196 init_smb_file_time(&ft
);
198 if (fsp
->fsp_flags
.posix_open
) {
199 /* Don't use delayed writes on POSIX files. */
203 if (fsp
->fsp_flags
.write_time_forced
) {
205 * No point - "sticky" write times
211 TALLOC_FREE(fsp
->update_write_time_event
);
212 DEBUG(5, ("Update write time immediate on %s\n",
215 /* After an immediate update, reset the trigger. */
216 fsp
->fsp_flags
.update_write_time_triggered
= true;
217 fsp
->fsp_flags
.update_write_time_on_close
= false;
219 ft
.mtime
= timespec_current();
221 /* Update the time in the open file db. */
222 (void)set_write_time(fsp
->file_id
, ft
.mtime
);
224 /* Now set on disk - takes care of notify. */
225 (void)smb_set_file_time(fsp
->conn
, fsp
, fsp
->fsp_name
, &ft
, false);
228 void mark_file_modified(files_struct
*fsp
)
232 trigger_write_time_update(fsp
);
234 if (fsp
->fsp_flags
.modified
) {
238 fsp
->fsp_flags
.modified
= true;
240 if (!(lp_store_dos_attributes(SNUM(fsp
->conn
)) ||
241 MAP_ARCHIVE(fsp
->conn
))) {
245 dosmode
= fdos_mode(fsp
);
246 if (dosmode
& FILE_ATTRIBUTE_ARCHIVE
) {
249 file_set_dosmode(fsp
->conn
, fsp
->fsp_name
,
250 dosmode
| FILE_ATTRIBUTE_ARCHIVE
, NULL
, false);
253 /****************************************************************************
255 ****************************************************************************/
257 ssize_t
write_file(struct smb_request
*req
,
263 ssize_t total_written
= 0;
265 if (fsp
->print_file
) {
269 ret
= print_spool_write(fsp
, data
, n
, pos
, &t
);
277 if (!fsp
->fsp_flags
.can_write
) {
282 mark_file_modified(fsp
);
285 * If this file is level II oplocked then we need
286 * to grab the shared memory lock and inform all
287 * other files with a level II lock that they need
288 * to flush their read caches. We keep the lock over
289 * the shared memory area whilst doing this.
292 /* This should actually be improved to span the write. */
293 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_WRITE
);
294 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_WRITE
);
296 total_written
= real_write_file(req
, fsp
, data
, pos
, n
);
297 return total_written
;
300 /*******************************************************************
302 ********************************************************************/
304 NTSTATUS
sync_file(connection_struct
*conn
, files_struct
*fsp
, bool write_through
)
306 if (fsp_get_io_fd(fsp
) == -1)
307 return NT_STATUS_INVALID_HANDLE
;
309 if (lp_strict_sync(SNUM(conn
)) &&
310 (lp_sync_always(SNUM(conn
)) || write_through
)) {
312 ret
= smb_vfs_fsync_sync(fsp
);
314 return map_nt_error_from_unix(errno
);