source: branches/samba-3.3.x/source/smbd/dosmode.c@ 244

Last change on this file since 244 was 244, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #41 in 3.3 branch

File size: 19.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 dos mode handling functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) James Peach 2006
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22
23static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
24{
25#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
26 if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
27 return FILE_ATTRIBUTE_SPARSE;
28 }
29#endif
30 return 0;
31}
32
33/****************************************************************************
34 Change a dos mode to a unix mode.
35 Base permission for files:
36 if creating file and inheriting (i.e. parent_dir != NULL)
37 apply read/write bits from parent directory.
38 else
39 everybody gets read bit set
40 dos readonly is represented in unix by removing everyone's write bit
41 dos archive is represented in unix by the user's execute bit
42 dos system is represented in unix by the group's execute bit
43 dos hidden is represented in unix by the other's execute bit
44 if !inheriting {
45 Then apply create mask,
46 then add force bits.
47 }
48 Base permission for directories:
49 dos directory is represented in unix by unix's dir bit and the exec bit
50 if !inheriting {
51 Then apply create mask,
52 then add force bits.
53 }
54****************************************************************************/
55
56mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
57 const char *inherit_from_dir)
58{
59 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
60 mode_t dir_mode = 0; /* Mode of the inherit_from directory if
61 * inheriting. */
62
63 if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
64 result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
65 }
66
67 if (fname && (inherit_from_dir != NULL)
68 && lp_inherit_perms(SNUM(conn))) {
69 SMB_STRUCT_STAT sbuf;
70
71 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
72 inherit_from_dir));
73 if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
74 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
75 inherit_from_dir, strerror(errno)));
76 return(0); /* *** shouldn't happen! *** */
77 }
78
79 /* Save for later - but explicitly remove setuid bit for safety. */
80 dir_mode = sbuf.st_mode & ~S_ISUID;
81 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
82 /* Clear "result" */
83 result = 0;
84 }
85
86 if (IS_DOS_DIR(dosmode)) {
87 /* We never make directories read only for the owner as under DOS a user
88 can always create a file in a read-only directory. */
89 result |= (S_IFDIR | S_IWUSR);
90
91 if (dir_mode) {
92 /* Inherit mode of parent directory. */
93 result |= dir_mode;
94 } else {
95 /* Provisionally add all 'x' bits */
96 result |= (S_IXUSR | S_IXGRP | S_IXOTH);
97
98 /* Apply directory mask */
99 result &= lp_dir_mask(SNUM(conn));
100 /* Add in force bits */
101 result |= lp_force_dir_mode(SNUM(conn));
102 }
103 } else {
104 if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
105 result |= S_IXUSR;
106
107 if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
108 result |= S_IXGRP;
109
110 if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
111 result |= S_IXOTH;
112
113 if (dir_mode) {
114 /* Inherit 666 component of parent directory mode */
115 result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
116 } else {
117 /* Apply mode mask */
118 result &= lp_create_mask(SNUM(conn));
119 /* Add in force bits */
120 result |= lp_force_create_mode(SNUM(conn));
121 }
122 }
123
124 DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
125 return(result);
126}
127
128/****************************************************************************
129 Change a unix mode to a dos mode.
130****************************************************************************/
131
132static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
133{
134 int result = 0;
135 enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
136
137 if (ro_opts == MAP_READONLY_YES) {
138 /* Original Samba method - map inverse of user "w" bit. */
139#ifndef __OS2__
140 if ((sbuf->st_mode & S_IWUSR) == 0) {
141#else
142 if(os2_isattribute(path,aRONLY)==0) {
143#endif
144 result |= aRONLY;
145 }
146 } else if (ro_opts == MAP_READONLY_PERMISSIONS) {
147 /* Check actual permissions for read-only. */
148 if (!can_write_to_file(conn, path, sbuf)) {
149 result |= aRONLY;
150 }
151 } /* Else never set the readonly bit. */
152
153#ifndef __OS2__
154 if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
155#else
156 if(os2_isattribute(path,aARCH)==0)
157#endif
158 result |= aARCH;
159
160#ifndef __OS2__
161 if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
162#else
163 if(os2_isattribute(path,aSYSTEM)==0)
164#endif
165 result |= aSYSTEM;
166
167#ifndef __OS2__
168 if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
169#else
170 if(os2_isattribute(path,aHIDDEN)==0)
171#endif
172 result |= aHIDDEN;
173
174 if (S_ISDIR(sbuf->st_mode))
175 result = aDIR | (result & aRONLY);
176
177 result |= set_sparse_flag(sbuf);
178
179#ifdef S_ISLNK
180#if LINKS_READ_ONLY
181 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
182 result |= aRONLY;
183#endif
184#endif
185
186 DEBUG(8,("dos_mode_from_sbuf returning "));
187
188 if (result & aHIDDEN) DEBUG(8, ("h"));
189 if (result & aRONLY ) DEBUG(8, ("r"));
190 if (result & aSYSTEM) DEBUG(8, ("s"));
191 if (result & aDIR ) DEBUG(8, ("d"));
192 if (result & aARCH ) DEBUG(8, ("a"));
193
194 DEBUG(8,("\n"));
195 return result;
196}
197
198/****************************************************************************
199 Get DOS attributes from an EA.
200****************************************************************************/
201
202static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
203{
204 ssize_t sizeret;
205 fstring attrstr;
206 unsigned int dosattr;
207
208 if (!lp_store_dos_attributes(SNUM(conn))) {
209 return False;
210 }
211
212 /* Don't reset pattr to zero as we may already have filename-based attributes we
213 need to preserve. */
214
215 sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
216 if (sizeret == -1) {
217 if (errno == ENOSYS
218#if defined(ENOTSUP)
219 || errno == ENOTSUP) {
220#else
221 ) {
222#endif
223#ifndef __OS2__
224 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
225 path, strerror(errno) ));
226#else
227 // HB On OS/2 no error in case of ./.. and errno == 2
228 if ((strncmp(path,"./..",4) != 0) || (errno != 2)) {
229 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
230 path, strerror(errno) ));
231
232 }
233#endif
234 set_store_dos_attributes(SNUM(conn), False);
235 }
236 return False;
237 }
238 /* Null terminate string. */
239 attrstr[sizeret] = 0;
240 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
241
242 if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
243 sscanf(attrstr, "%x", &dosattr) != 1) {
244 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
245 return False;
246 }
247
248 if (S_ISDIR(sbuf->st_mode)) {
249 dosattr |= aDIR;
250 }
251 *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
252
253 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
254
255 if (dosattr & aHIDDEN) DEBUG(8, ("h"));
256 if (dosattr & aRONLY ) DEBUG(8, ("r"));
257 if (dosattr & aSYSTEM) DEBUG(8, ("s"));
258 if (dosattr & aDIR ) DEBUG(8, ("d"));
259 if (dosattr & aARCH ) DEBUG(8, ("a"));
260
261 DEBUG(8,("\n"));
262
263 return True;
264}
265
266/****************************************************************************
267 Set DOS attributes in an EA.
268****************************************************************************/
269
270static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
271{
272 fstring attrstr;
273 files_struct *fsp = NULL;
274 bool ret = False;
275
276 if (!lp_store_dos_attributes(SNUM(conn))) {
277 return False;
278 }
279
280 snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
281 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
282 if((errno != EPERM) && (errno != EACCES)) {
283 if (errno == ENOSYS
284#if defined(ENOTSUP)
285 || errno == ENOTSUP) {
286#else
287 ) {
288#endif
289 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
290 path, strerror(errno) ));
291 set_store_dos_attributes(SNUM(conn), False);
292 }
293 return False;
294 }
295
296 /* We want DOS semantics, ie allow non owner with write permission to change the
297 bits on a file. Just like file_ntimes below.
298 */
299
300 /* Check if we have write access. */
301 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
302 return False;
303
304 /*
305 * We need to open the file with write access whilst
306 * still in our current user context. This ensures we
307 * are not violating security in doing the setxattr.
308 */
309
310 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
311 return ret;
312 become_root();
313 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
314 ret = True;
315 }
316 unbecome_root();
317 close_file_fchmod(fsp);
318 return ret;
319 }
320 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
321 return True;
322}
323
324/****************************************************************************
325 Change a unix mode to a dos mode for an ms dfs link.
326****************************************************************************/
327
328uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
329{
330 uint32 result = 0;
331
332 DEBUG(8,("dos_mode_msdfs: %s\n", path));
333
334 if (!VALID_STAT(*sbuf)) {
335 return 0;
336 }
337
338 /* First do any modifications that depend on the path name. */
339 /* hide files with a name starting with a . */
340 if (lp_hide_dot_files(SNUM(conn))) {
341 const char *p = strrchr_m(path,'/');
342 if (p) {
343 p++;
344 } else {
345 p = path;
346 }
347
348 /* Only . and .. are not hidden. */
349 if (p[0] == '.' && !((p[1] == '\0') ||
350 (p[1] == '.' && p[2] == '\0'))) {
351 result |= aHIDDEN;
352 }
353 }
354
355 result |= dos_mode_from_sbuf(conn, path, sbuf);
356
357 /* Optimization : Only call is_hidden_path if it's not already
358 hidden. */
359 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
360 result |= aHIDDEN;
361 }
362
363 DEBUG(8,("dos_mode_msdfs returning "));
364
365 if (result & aHIDDEN) DEBUG(8, ("h"));
366 if (result & aRONLY ) DEBUG(8, ("r"));
367 if (result & aSYSTEM) DEBUG(8, ("s"));
368 if (result & aDIR ) DEBUG(8, ("d"));
369 if (result & aARCH ) DEBUG(8, ("a"));
370 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
371
372 DEBUG(8,("\n"));
373
374 return(result);
375}
376
377/****************************************************************************
378 Change a unix mode to a dos mode.
379****************************************************************************/
380
381uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
382{
383 uint32 result = 0;
384 bool offline;
385
386 DEBUG(8,("dos_mode: %s\n", path));
387
388 if (!VALID_STAT(*sbuf)) {
389 return 0;
390 }
391
392 /* First do any modifications that depend on the path name. */
393 /* hide files with a name starting with a . */
394 if (lp_hide_dot_files(SNUM(conn))) {
395 const char *p = strrchr_m(path,'/');
396 if (p) {
397 p++;
398 } else {
399 p = path;
400 }
401
402 /* Only . and .. are not hidden. */
403 if (p[0] == '.' && !((p[1] == '\0') ||
404 (p[1] == '.' && p[2] == '\0'))) {
405 result |= aHIDDEN;
406 }
407 }
408
409 /* Get the DOS attributes from an EA by preference. */
410 if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
411 result |= set_sparse_flag(sbuf);
412 } else {
413 result |= dos_mode_from_sbuf(conn, path, sbuf);
414 }
415
416
417 offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf);
418 if (S_ISREG(sbuf->st_mode) && offline) {
419 result |= FILE_ATTRIBUTE_OFFLINE;
420 }
421
422 /* Optimization : Only call is_hidden_path if it's not already
423 hidden. */
424 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
425 result |= aHIDDEN;
426 }
427
428 DEBUG(8,("dos_mode returning "));
429
430 if (result & aHIDDEN) DEBUG(8, ("h"));
431 if (result & aRONLY ) DEBUG(8, ("r"));
432 if (result & aSYSTEM) DEBUG(8, ("s"));
433 if (result & aDIR ) DEBUG(8, ("d"));
434 if (result & aARCH ) DEBUG(8, ("a"));
435 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
436
437 DEBUG(8,("\n"));
438
439 return(result);
440}
441
442/*******************************************************************
443 chmod a file - but preserve some bits.
444********************************************************************/
445
446int file_set_dosmode(connection_struct *conn, const char *fname,
447 uint32 dosmode, SMB_STRUCT_STAT *st,
448 const char *parent_dir,
449 bool newfile)
450{
451 SMB_STRUCT_STAT st1;
452 int mask=0;
453 mode_t tmp;
454 mode_t unixmode;
455 int ret = -1, lret = -1;
456 uint32_t old_mode;
457
458 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
459 dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
460
461 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
462
463 if (st == NULL) {
464 SET_STAT_INVALID(st1);
465 st = &st1;
466 }
467
468 if (!VALID_STAT(*st)) {
469 if (SMB_VFS_STAT(conn,fname,st))
470 return(-1);
471 }
472
473 unixmode = st->st_mode;
474
475 get_acl_group_bits(conn, fname, &st->st_mode);
476
477 if (S_ISDIR(st->st_mode))
478 dosmode |= aDIR;
479 else
480 dosmode &= ~aDIR;
481
482 old_mode = dos_mode(conn,fname,st);
483
484 if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
485 if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
486 lret = SMB_VFS_SET_OFFLINE(conn, fname);
487 if (lret == -1) {
488 DEBUG(0, ("set_dos_mode: client has asked to set "
489 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
490 "an error while setting it or it is not supported.\n",
491 parent_dir, fname));
492 }
493 }
494 }
495
496 dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
497 old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
498
499 if (old_mode == dosmode) {
500 st->st_mode = unixmode;
501 return(0);
502 }
503
504 /* Store the DOS attributes in an EA by preference. */
505 if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
506 if (!newfile) {
507 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
508 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
509 }
510 st->st_mode = unixmode;
511 return 0;
512 }
513
514 unixmode = unix_mode(conn,dosmode,fname, parent_dir);
515
516 /* preserve the s bits */
517 mask |= (S_ISUID | S_ISGID);
518
519 /* preserve the t bit */
520#ifdef S_ISVTX
521 mask |= S_ISVTX;
522#endif
523
524 /* possibly preserve the x bits */
525 if (!MAP_ARCHIVE(conn))
526 mask |= S_IXUSR;
527 if (!MAP_SYSTEM(conn))
528 mask |= S_IXGRP;
529 if (!MAP_HIDDEN(conn))
530 mask |= S_IXOTH;
531
532 unixmode |= (st->st_mode & mask);
533
534 /* if we previously had any r bits set then leave them alone */
535 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
536 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
537 unixmode |= tmp;
538 }
539
540 /* if we previously had any w bits set then leave them alone
541 whilst adding in the new w bits, if the new mode is not rdonly */
542 if (!IS_DOS_READONLY(dosmode)) {
543 unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
544 }
545
546 ret = SMB_VFS_CHMOD(conn, fname, unixmode);
547 if (ret == 0) {
548 if(!newfile || (lret != -1)) {
549 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
550 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
551 }
552 st->st_mode = unixmode;
553 return 0;
554 }
555
556 if((errno != EPERM) && (errno != EACCES))
557 return -1;
558
559 if(!lp_dos_filemode(SNUM(conn)))
560 return -1;
561
562 /* We want DOS semantics, ie allow non owner with write permission to change the
563 bits on a file. Just like file_ntimes below.
564 */
565
566 /* Check if we have write access. */
567 if (CAN_WRITE(conn)) {
568 /*
569 * We need to open the file with write access whilst
570 * still in our current user context. This ensures we
571 * are not violating security in doing the fchmod.
572 * This file open does *not* break any oplocks we are
573 * holding. We need to review this.... may need to
574 * break batch oplocks open by others. JRA.
575 */
576 files_struct *fsp;
577 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
578 return -1;
579 become_root();
580 ret = SMB_VFS_FCHMOD(fsp, unixmode);
581 unbecome_root();
582 close_file_fchmod(fsp);
583 if (!newfile) {
584 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
585 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
586 }
587 if (ret == 0) {
588 st->st_mode = unixmode;
589 }
590 }
591
592 return( ret );
593}
594
595/*******************************************************************
596 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
597 than POSIX.
598*******************************************************************/
599
600int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
601{
602 SMB_STRUCT_STAT sbuf;
603 int ret = -1;
604
605 errno = 0;
606 ZERO_STRUCT(sbuf);
607
608 DEBUG(6, ("file_ntime: actime: %s",
609 time_to_asc(convert_timespec_to_time_t(ts[0]))));
610 DEBUG(6, ("file_ntime: modtime: %s",
611 time_to_asc(convert_timespec_to_time_t(ts[1]))));
612
613 /* Don't update the time on read-only shares */
614 /* We need this as set_filetime (which can be called on
615 close and other paths) can end up calling this function
616 without the NEED_WRITE protection. Found by :
617 Leo Weppelman <leo@wau.mis.ah.nl>
618 */
619
620 if (!CAN_WRITE(conn)) {
621 return 0;
622 }
623
624 if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
625 return 0;
626 }
627
628 if((errno != EPERM) && (errno != EACCES)) {
629 return -1;
630 }
631
632 if(!lp_dos_filetimes(SNUM(conn))) {
633 return -1;
634 }
635
636 /* We have permission (given by the Samba admin) to
637 break POSIX semantics and allow a user to change
638 the time on a file they don't own but can write to
639 (as DOS does).
640 */
641
642 /* Check if we have write access. */
643 if (can_write_to_file(conn, fname, &sbuf)) {
644 /* We are allowed to become root and change the filetime. */
645 become_root();
646 ret = SMB_VFS_NTIMES(conn, fname, ts);
647 unbecome_root();
648 }
649
650 return ret;
651}
652
653/******************************************************************
654 Force a "sticky" write time on a pathname. This will always be
655 returned on all future write time queries and set on close.
656******************************************************************/
657
658bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
659 struct file_id fileid, const struct timespec mtime)
660{
661 if (null_timespec(mtime)) {
662 return true;
663 }
664
665 if (!set_sticky_write_time(fileid, mtime)) {
666 return false;
667 }
668
669 return true;
670}
671
672/******************************************************************
673 Force a "sticky" write time on an fsp. This will always be
674 returned on all future write time queries and set on close.
675******************************************************************/
676
677bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
678{
679 fsp->write_time_forced = true;
680 TALLOC_FREE(fsp->update_write_time_event);
681
682 return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
683 fsp->file_id, mtime);
684}
685
686/******************************************************************
687 Update a write time immediately, without the 2 second delay.
688******************************************************************/
689
690bool update_write_time(struct files_struct *fsp)
691{
692 if (!set_write_time(fsp->file_id, timespec_current())) {
693 return false;
694 }
695
696 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
697 FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
698
699 return true;
700}
Note: See TracBrowser for help on using the repository browser.