Line data Source code
1 : /*
2 : Unix SMB/Netbios implementation.
3 : Version 1.9.
4 : read/write to a files_struct
5 : Copyright (C) Andrew Tridgell 1992-1998
6 : Copyright (C) Jeremy Allison 2000-2002. - write cache.
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "printing.h"
24 : #include "smbd/smbd.h"
25 : #include "smbd/globals.h"
26 : #include "smbprofile.h"
27 :
28 : /****************************************************************************
29 : Read from a file.
30 : ****************************************************************************/
31 :
32 0 : ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n)
33 : {
34 : off_t new_pos;
35 0 : ssize_t ret = 0;
36 : bool ok;
37 :
38 : /* you can't read from print files */
39 0 : if (fsp->print_file) {
40 0 : errno = EBADF;
41 0 : return -1;
42 : }
43 :
44 0 : ok = vfs_valid_pread_range(pos, n);
45 0 : if (!ok) {
46 0 : errno = EINVAL;
47 0 : return -1;
48 : }
49 :
50 0 : fh_set_pos(fsp->fh, pos);
51 :
52 0 : if (n > 0) {
53 0 : ret = SMB_VFS_PREAD(fsp,data,n,pos);
54 :
55 0 : if (ret == -1) {
56 0 : return -1;
57 : }
58 : }
59 :
60 0 : DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
61 : fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
62 :
63 0 : new_pos = fh_get_pos(fsp->fh) + ret;
64 0 : fh_set_pos(fsp->fh, new_pos);
65 0 : fh_set_position_information(fsp->fh, new_pos);
66 :
67 0 : return(ret);
68 : }
69 :
70 : /****************************************************************************
71 : *Really* write to a file.
72 : ****************************************************************************/
73 :
74 24 : static ssize_t real_write_file(struct smb_request *req,
75 : files_struct *fsp,
76 : const char *data,
77 : off_t pos,
78 : size_t n)
79 : {
80 : ssize_t ret;
81 : bool ok;
82 :
83 24 : ok = vfs_valid_pwrite_range(pos, n);
84 24 : if (!ok) {
85 0 : errno = EINVAL;
86 0 : return -1;
87 : }
88 :
89 24 : if (n == 0) {
90 0 : return 0;
91 : }
92 :
93 24 : fh_set_pos(fsp->fh, pos);
94 24 : if (pos &&
95 0 : lp_strict_allocate(SNUM(fsp->conn)) &&
96 0 : !fsp->fsp_flags.is_sparse)
97 : {
98 0 : if (vfs_fill_sparse(fsp, pos) == -1) {
99 0 : return -1;
100 : }
101 : }
102 24 : ret = vfs_pwrite_data(req, fsp, data, n, pos);
103 :
104 24 : 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));
106 :
107 24 : if (ret != -1) {
108 24 : off_t new_pos = fh_get_pos(fsp->fh) + ret;
109 24 : fh_set_pos(fsp->fh, new_pos);
110 :
111 : /* Yes - this is correct - writes don't update this. JRA. */
112 : /* Found by Samba4 tests. */
113 : #if 0
114 : fsp->position_information = fsp->pos;
115 : #endif
116 : }
117 :
118 24 : return ret;
119 : }
120 :
121 436 : void fsp_flush_write_time_update(struct files_struct *fsp)
122 : {
123 : /*
124 : * Note this won't expect any impersonation!
125 : * So don't call any SMB_VFS operations here!
126 : */
127 :
128 436 : DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp)));
129 :
130 436 : trigger_write_time_update_immediate(fsp);
131 436 : }
132 :
133 0 : static void update_write_time_handler(struct tevent_context *ctx,
134 : struct tevent_timer *te,
135 : struct timeval now,
136 : void *private_data)
137 : {
138 0 : files_struct *fsp = (files_struct *)private_data;
139 0 : fsp_flush_write_time_update(fsp);
140 0 : }
141 :
142 : /*********************************************************
143 : Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
144 : in the future.
145 : *********************************************************/
146 :
147 447 : void trigger_write_time_update(struct files_struct *fsp)
148 : {
149 : int delay;
150 :
151 447 : if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
152 : /* Don't use delayed writes on POSIX files. */
153 0 : return;
154 : }
155 :
156 447 : if (fsp->fsp_flags.write_time_forced) {
157 : /* No point - "sticky" write times
158 : * in effect.
159 : */
160 0 : return;
161 : }
162 :
163 : /* We need to remember someone did a write
164 : * and update to current time on close. */
165 :
166 447 : fsp->fsp_flags.update_write_time_on_close = true;
167 :
168 447 : if (fsp->fsp_flags.update_write_time_triggered) {
169 : /*
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.
173 : */
174 10 : return;
175 : }
176 437 : fsp->fsp_flags.update_write_time_triggered = true;
177 :
178 437 : delay = lp_parm_int(SNUM(fsp->conn),
179 : "smbd", "writetimeupdatedelay",
180 : WRITE_TIME_UPDATE_USEC_DELAY);
181 :
182 437 : DEBUG(5, ("Update write time %d usec later on %s\n",
183 : delay, fsp_str_dbg(fsp)));
184 :
185 : /* trigger the update 2 seconds later */
186 437 : fsp->update_write_time_event =
187 437 : tevent_add_timer(fsp->conn->sconn->ev_ctx, NULL,
188 : timeval_current_ofs_usec(delay),
189 : update_write_time_handler, fsp);
190 : }
191 :
192 437 : void trigger_write_time_update_immediate(struct files_struct *fsp)
193 : {
194 : struct smb_file_time ft;
195 :
196 437 : init_smb_file_time(&ft);
197 :
198 437 : if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
199 : /* Don't use delayed writes on POSIX files. */
200 1 : return;
201 : }
202 :
203 437 : if (fsp->fsp_flags.write_time_forced) {
204 : /*
205 : * No point - "sticky" write times
206 : * in effect.
207 : */
208 1 : return;
209 : }
210 :
211 436 : TALLOC_FREE(fsp->update_write_time_event);
212 436 : DEBUG(5, ("Update write time immediate on %s\n",
213 : fsp_str_dbg(fsp)));
214 :
215 : /* After an immediate update, reset the trigger. */
216 436 : fsp->fsp_flags.update_write_time_triggered = true;
217 436 : fsp->fsp_flags.update_write_time_on_close = false;
218 :
219 436 : ft.mtime = timespec_current();
220 :
221 : /* Update the time in the open file db. */
222 436 : (void)set_write_time(fsp->file_id, ft.mtime);
223 :
224 : /* Now set on disk - takes care of notify. */
225 436 : (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
226 : }
227 :
228 447 : void mark_file_modified(files_struct *fsp)
229 : {
230 : int dosmode;
231 :
232 447 : trigger_write_time_update(fsp);
233 :
234 447 : if (fsp->fsp_flags.modified) {
235 10 : return;
236 : }
237 :
238 437 : fsp->fsp_flags.modified = true;
239 :
240 437 : if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
241 0 : return;
242 : }
243 437 : if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
244 0 : MAP_ARCHIVE(fsp->conn))) {
245 0 : return;
246 : }
247 :
248 437 : dosmode = fdos_mode(fsp);
249 437 : if (IS_DOS_ARCHIVE(dosmode)) {
250 437 : return;
251 : }
252 0 : file_set_dosmode(fsp->conn, fsp->fsp_name,
253 : dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false);
254 : }
255 :
256 : /****************************************************************************
257 : Write to a file.
258 : ****************************************************************************/
259 :
260 24 : ssize_t write_file(struct smb_request *req,
261 : files_struct *fsp,
262 : const char *data,
263 : off_t pos,
264 : size_t n)
265 : {
266 24 : ssize_t total_written = 0;
267 :
268 24 : if (fsp->print_file) {
269 : uint32_t t;
270 : int ret;
271 :
272 0 : ret = print_spool_write(fsp, data, n, pos, &t);
273 0 : if (ret) {
274 0 : errno = ret;
275 0 : return -1;
276 : }
277 0 : return t;
278 : }
279 :
280 24 : if (!fsp->fsp_flags.can_write) {
281 0 : errno = EPERM;
282 0 : return -1;
283 : }
284 :
285 24 : mark_file_modified(fsp);
286 :
287 : /*
288 : * If this file is level II oplocked then we need
289 : * to grab the shared memory lock and inform all
290 : * other files with a level II lock that they need
291 : * to flush their read caches. We keep the lock over
292 : * the shared memory area whilst doing this.
293 : */
294 :
295 : /* This should actually be improved to span the write. */
296 24 : contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
297 24 : contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
298 :
299 24 : total_written = real_write_file(req, fsp, data, pos, n);
300 24 : return total_written;
301 : }
302 :
303 : /*******************************************************************
304 : sync a file
305 : ********************************************************************/
306 :
307 24 : NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through)
308 : {
309 24 : if (fsp_get_io_fd(fsp) == -1)
310 0 : return NT_STATUS_INVALID_HANDLE;
311 :
312 48 : if (lp_strict_sync(SNUM(conn)) &&
313 48 : (lp_sync_always(SNUM(conn)) || write_through)) {
314 : int ret;
315 0 : ret = smb_vfs_fsync_sync(fsp);
316 0 : if (ret == -1) {
317 0 : return map_nt_error_from_unix(errno);
318 : }
319 : }
320 24 : return NT_STATUS_OK;
321 : }
|