2 Unix SMB/CIFS implementation.
3 dos mode handling functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) James Peach 2006
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.
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.
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/>.
23 static int set_sparse_flag(const SMB_STRUCT_STAT
* const sbuf
)
25 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
26 if (sbuf
->st_ex_size
> sbuf
->st_ex_blocks
* (SMB_OFF_T
)STAT_ST_BLOCKSIZE
) {
27 return FILE_ATTRIBUTE_SPARSE
;
33 static int set_link_read_only_flag(const SMB_STRUCT_STAT
*const sbuf
)
37 if (S_ISLNK(sbuf
->st_mode
) && S_ISDIR(sbuf
->st_mode
))
44 /****************************************************************************
45 Change a dos mode to a unix mode.
46 Base permission for files:
47 if creating file and inheriting (i.e. parent_dir != NULL)
48 apply read/write bits from parent directory.
50 everybody gets read bit set
51 dos readonly is represented in unix by removing everyone's write bit
52 dos archive is represented in unix by the user's execute bit
53 dos system is represented in unix by the group's execute bit
54 dos hidden is represented in unix by the other's execute bit
56 Then apply create mask,
59 Base permission for directories:
60 dos directory is represented in unix by unix's dir bit and the exec bit
62 Then apply create mask,
65 ****************************************************************************/
67 mode_t
unix_mode(connection_struct
*conn
, int dosmode
, const char *fname
,
68 const char *inherit_from_dir
)
70 mode_t result
= (S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
);
71 mode_t dir_mode
= 0; /* Mode of the inherit_from directory if
74 if (!lp_store_dos_attributes(SNUM(conn
)) && IS_DOS_READONLY(dosmode
)) {
75 result
&= ~(S_IWUSR
| S_IWGRP
| S_IWOTH
);
78 if (fname
&& (inherit_from_dir
!= NULL
)
79 && lp_inherit_perms(SNUM(conn
))) {
82 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname
,
84 if (SMB_VFS_STAT(conn
, inherit_from_dir
, &sbuf
) != 0) {
85 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname
,
86 inherit_from_dir
, strerror(errno
)));
87 return(0); /* *** shouldn't happen! *** */
90 /* Save for later - but explicitly remove setuid bit for safety. */
91 dir_mode
= sbuf
.st_ex_mode
& ~S_ISUID
;
92 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname
,(int)dir_mode
));
97 if (IS_DOS_DIR(dosmode
)) {
98 /* We never make directories read only for the owner as under DOS a user
99 can always create a file in a read-only directory. */
100 result
|= (S_IFDIR
| S_IWUSR
);
103 /* Inherit mode of parent directory. */
106 /* Provisionally add all 'x' bits */
107 result
|= (S_IXUSR
| S_IXGRP
| S_IXOTH
);
109 /* Apply directory mask */
110 result
&= lp_dir_mask(SNUM(conn
));
111 /* Add in force bits */
112 result
|= lp_force_dir_mode(SNUM(conn
));
115 if (lp_map_archive(SNUM(conn
)) && IS_DOS_ARCHIVE(dosmode
))
118 if (lp_map_system(SNUM(conn
)) && IS_DOS_SYSTEM(dosmode
))
121 if (lp_map_hidden(SNUM(conn
)) && IS_DOS_HIDDEN(dosmode
))
125 /* Inherit 666 component of parent directory mode */
126 result
|= dir_mode
& (S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
);
128 /* Apply mode mask */
129 result
&= lp_create_mask(SNUM(conn
));
130 /* Add in force bits */
131 result
|= lp_force_create_mode(SNUM(conn
));
135 DEBUG(3,("unix_mode(%s) returning 0%o\n",fname
,(int)result
));
139 /****************************************************************************
140 Change a unix mode to a dos mode.
141 ****************************************************************************/
143 static uint32
dos_mode_from_sbuf(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
)
146 enum mapreadonly_options ro_opts
= (enum mapreadonly_options
)lp_map_readonly(SNUM(conn
));
148 if (ro_opts
== MAP_READONLY_YES
) {
149 /* Original Samba method - map inverse of user "w" bit. */
150 if ((sbuf
->st_ex_mode
& S_IWUSR
) == 0) {
153 } else if (ro_opts
== MAP_READONLY_PERMISSIONS
) {
154 /* Check actual permissions for read-only. */
155 if (!can_write_to_file(conn
, path
, sbuf
)) {
158 } /* Else never set the readonly bit. */
160 if (MAP_ARCHIVE(conn
) && ((sbuf
->st_ex_mode
& S_IXUSR
) != 0))
163 if (MAP_SYSTEM(conn
) && ((sbuf
->st_ex_mode
& S_IXGRP
) != 0))
166 if (MAP_HIDDEN(conn
) && ((sbuf
->st_ex_mode
& S_IXOTH
) != 0))
169 if (S_ISDIR(sbuf
->st_ex_mode
))
170 result
= aDIR
| (result
& aRONLY
);
172 result
|= set_sparse_flag(sbuf
);
173 result
|= set_link_read_only_flag(sbuf
);
175 DEBUG(8,("dos_mode_from_sbuf returning "));
177 if (result
& aHIDDEN
) DEBUG(8, ("h"));
178 if (result
& aRONLY
) DEBUG(8, ("r"));
179 if (result
& aSYSTEM
) DEBUG(8, ("s"));
180 if (result
& aDIR
) DEBUG(8, ("d"));
181 if (result
& aARCH
) DEBUG(8, ("a"));
187 /****************************************************************************
188 Get DOS attributes from an EA.
189 ****************************************************************************/
191 static bool get_ea_dos_attribute(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
, uint32
*pattr
)
195 unsigned int dosattr
;
197 if (!lp_store_dos_attributes(SNUM(conn
))) {
201 /* Don't reset pattr to zero as we may already have filename-based attributes we
204 sizeret
= SMB_VFS_GETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, sizeof(attrstr
));
208 || errno
== ENOTSUP
) {
212 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
213 path
, strerror(errno
) ));
214 set_store_dos_attributes(SNUM(conn
), False
);
218 /* Null terminate string. */
219 attrstr
[sizeret
] = 0;
220 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path
, attrstr
));
222 if (sizeret
< 2 || attrstr
[0] != '0' || attrstr
[1] != 'x' ||
223 sscanf(attrstr
, "%x", &dosattr
) != 1) {
224 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path
, attrstr
));
228 if (S_ISDIR(sbuf
->st_ex_mode
)) {
231 *pattr
= (uint32
)(dosattr
& SAMBA_ATTRIBUTES_MASK
);
233 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr
));
235 if (dosattr
& aHIDDEN
) DEBUG(8, ("h"));
236 if (dosattr
& aRONLY
) DEBUG(8, ("r"));
237 if (dosattr
& aSYSTEM
) DEBUG(8, ("s"));
238 if (dosattr
& aDIR
) DEBUG(8, ("d"));
239 if (dosattr
& aARCH
) DEBUG(8, ("a"));
246 /****************************************************************************
247 Set DOS attributes in an EA.
248 ****************************************************************************/
250 static bool set_ea_dos_attribute(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
, uint32 dosmode
)
253 files_struct
*fsp
= NULL
;
256 if (!lp_store_dos_attributes(SNUM(conn
))) {
260 snprintf(attrstr
, sizeof(attrstr
)-1, "0x%x", dosmode
& SAMBA_ATTRIBUTES_MASK
);
261 if (SMB_VFS_SETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, strlen(attrstr
), 0) == -1) {
262 if((errno
!= EPERM
) && (errno
!= EACCES
)) {
265 || errno
== ENOTSUP
) {
269 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
270 path
, strerror(errno
) ));
271 set_store_dos_attributes(SNUM(conn
), False
);
276 /* We want DOS semantics, ie allow non owner with write permission to change the
277 bits on a file. Just like file_ntimes below.
280 /* Check if we have write access. */
281 if(!CAN_WRITE(conn
) || !lp_dos_filemode(SNUM(conn
)))
285 * We need to open the file with write access whilst
286 * still in our current user context. This ensures we
287 * are not violating security in doing the setxattr.
290 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL
, conn
, path
, sbuf
,
294 if (SMB_VFS_SETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, strlen(attrstr
), 0) == 0) {
298 close_file_fchmod(NULL
, fsp
);
301 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr
, path
));
305 /****************************************************************************
306 Change a unix mode to a dos mode for an ms dfs link.
307 ****************************************************************************/
309 uint32
dos_mode_msdfs(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
)
313 DEBUG(8,("dos_mode_msdfs: %s\n", path
));
315 if (!VALID_STAT(*sbuf
)) {
319 /* First do any modifications that depend on the path name. */
320 /* hide files with a name starting with a . */
321 if (lp_hide_dot_files(SNUM(conn
))) {
322 const char *p
= strrchr_m(path
,'/');
329 /* Only . and .. are not hidden. */
330 if (p
[0] == '.' && !((p
[1] == '\0') ||
331 (p
[1] == '.' && p
[2] == '\0'))) {
336 result
|= dos_mode_from_sbuf(conn
, path
, sbuf
);
338 /* Optimization : Only call is_hidden_path if it's not already
340 if (!(result
& aHIDDEN
) && IS_HIDDEN_PATH(conn
,path
)) {
344 DEBUG(8,("dos_mode_msdfs returning "));
346 if (result
& aHIDDEN
) DEBUG(8, ("h"));
347 if (result
& aRONLY
) DEBUG(8, ("r"));
348 if (result
& aSYSTEM
) DEBUG(8, ("s"));
349 if (result
& aDIR
) DEBUG(8, ("d"));
350 if (result
& aARCH
) DEBUG(8, ("a"));
351 if (result
& FILE_ATTRIBUTE_SPARSE
) DEBUG(8, ("[sparse]"));
358 #ifdef HAVE_STAT_DOS_FLAGS
359 /****************************************************************************
360 Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*)
361 ****************************************************************************/
363 int dos_attributes_to_stat_dos_flags(uint32_t dosmode
)
365 uint32_t dos_stat_flags
= 0;
368 dos_stat_flags
|= UF_DOS_ARCHIVE
;
369 if (dosmode
& aHIDDEN
)
370 dos_stat_flags
|= UF_DOS_HIDDEN
;
371 if (dosmode
& aRONLY
)
372 dos_stat_flags
|= UF_DOS_RO
;
373 if (dosmode
& aSYSTEM
)
374 dos_stat_flags
|= UF_DOS_SYSTEM
;
375 if (dosmode
& FILE_ATTRIBUTE_NONINDEXED
)
376 dos_stat_flags
|= UF_DOS_NOINDEX
;
378 return dos_stat_flags
;
381 /****************************************************************************
382 Gets DOS attributes, accessed via st_flags in the stat struct.
383 ****************************************************************************/
385 static bool get_stat_dos_flags(connection_struct
*conn
,
387 const SMB_STRUCT_STAT
*sbuf
,
390 SMB_ASSERT(sbuf
&& VALID_STAT(*sbuf
));
393 if (!lp_store_dos_attributes(SNUM(conn
))) {
397 DEBUG(5, ("Getting stat dos attributes for %s.\n", fname
));
399 if (sbuf
->st_flags
& UF_DOS_ARCHIVE
)
401 if (sbuf
->st_flags
& UF_DOS_HIDDEN
)
403 if (sbuf
->st_flags
& UF_DOS_RO
)
405 if (sbuf
->st_flags
& UF_DOS_SYSTEM
)
407 if (sbuf
->st_flags
& UF_DOS_NOINDEX
)
408 *dosmode
|= FILE_ATTRIBUTE_NONINDEXED
;
409 if (S_ISDIR(sbuf
->st_ex_mode
))
412 *dosmode
|= set_sparse_flag(sbuf
);
413 *dosmode
|= set_link_read_only_flag(sbuf
);
418 /****************************************************************************
419 Sets DOS attributes, stored in st_flags of the inode.
420 ****************************************************************************/
422 static bool set_stat_dos_flags(connection_struct
*conn
,
424 SMB_STRUCT_STAT
*sbuf
,
426 bool *attributes_changed
)
428 uint32_t new_flags
= 0;
431 SMB_ASSERT(sbuf
&& VALID_STAT(*sbuf
));
432 SMB_ASSERT(attributes_changed
);
434 *attributes_changed
= false;
436 if (!lp_store_dos_attributes(SNUM(conn
))) {
440 DEBUG(5, ("Setting stat dos attributes for %s.\n", fname
));
442 new_flags
= (sbuf
->st_flags
& ~UF_DOS_FLAGS
) |
443 dos_attributes_to_stat_dos_flags(dosmode
);
445 /* Return early if no flags changed. */
446 if (new_flags
== sbuf
->st_flags
)
449 DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags
,
452 /* Set new flags with chflags. */
453 error
= SMB_VFS_CHFLAGS(conn
, fname
, new_flags
);
455 DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
456 "file %s! errno=%d\n", new_flags
, fname
, errno
));
460 *attributes_changed
= true;
463 #endif /* HAVE_STAT_DOS_FLAGS */
465 /****************************************************************************
466 Change a unix mode to a dos mode.
467 ****************************************************************************/
469 uint32
dos_mode(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
)
472 bool offline
, used_stat_dos_flags
= false;
474 DEBUG(8,("dos_mode: %s\n", path
));
476 if (!VALID_STAT(*sbuf
)) {
480 /* First do any modifications that depend on the path name. */
481 /* hide files with a name starting with a . */
482 if (lp_hide_dot_files(SNUM(conn
))) {
483 const char *p
= strrchr_m(path
,'/');
490 /* Only . and .. are not hidden. */
491 if (p
[0] == '.' && !((p
[1] == '\0') ||
492 (p
[1] == '.' && p
[2] == '\0'))) {
497 #ifdef HAVE_STAT_DOS_FLAGS
498 used_stat_dos_flags
= get_stat_dos_flags(conn
, path
, sbuf
, &result
);
500 if (!used_stat_dos_flags
) {
501 /* Get the DOS attributes from an EA by preference. */
502 if (get_ea_dos_attribute(conn
, path
, sbuf
, &result
)) {
503 result
|= set_sparse_flag(sbuf
);
505 result
|= dos_mode_from_sbuf(conn
, path
, sbuf
);
509 offline
= SMB_VFS_IS_OFFLINE(conn
, path
, sbuf
);
510 if (S_ISREG(sbuf
->st_ex_mode
) && offline
) {
511 result
|= FILE_ATTRIBUTE_OFFLINE
;
514 /* Optimization : Only call is_hidden_path if it's not already
516 if (!(result
& aHIDDEN
) && IS_HIDDEN_PATH(conn
,path
)) {
520 DEBUG(8,("dos_mode returning "));
522 if (result
& aHIDDEN
) DEBUG(8, ("h"));
523 if (result
& aRONLY
) DEBUG(8, ("r"));
524 if (result
& aSYSTEM
) DEBUG(8, ("s"));
525 if (result
& aDIR
) DEBUG(8, ("d"));
526 if (result
& aARCH
) DEBUG(8, ("a"));
527 if (result
& FILE_ATTRIBUTE_SPARSE
) DEBUG(8, ("[sparse]"));
534 /*******************************************************************
535 chmod a file - but preserve some bits.
536 ********************************************************************/
538 int file_set_dosmode(connection_struct
*conn
, const char *fname
,
539 uint32 dosmode
, SMB_STRUCT_STAT
*st
,
540 const char *parent_dir
,
547 int ret
= -1, lret
= -1;
550 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
551 dosmode
&= (SAMBA_ATTRIBUTES_MASK
| FILE_ATTRIBUTE_OFFLINE
);
553 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode
, fname
));
556 SET_STAT_INVALID(st1
);
560 if (!VALID_STAT(*st
)) {
561 if (SMB_VFS_STAT(conn
,fname
,st
))
565 unixmode
= st
->st_ex_mode
;
567 get_acl_group_bits(conn
, fname
, &st
->st_ex_mode
);
569 if (S_ISDIR(st
->st_ex_mode
))
574 old_mode
= dos_mode(conn
,fname
,st
);
576 if (dosmode
& FILE_ATTRIBUTE_OFFLINE
) {
577 if (!(old_mode
& FILE_ATTRIBUTE_OFFLINE
)) {
578 lret
= SMB_VFS_SET_OFFLINE(conn
, fname
);
580 DEBUG(0, ("set_dos_mode: client has asked to set "
581 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
582 "an error while setting it or it is not supported.\n",
588 dosmode
&= ~FILE_ATTRIBUTE_OFFLINE
;
589 old_mode
&= ~FILE_ATTRIBUTE_OFFLINE
;
591 if (old_mode
== dosmode
) {
592 st
->st_ex_mode
= unixmode
;
596 #ifdef HAVE_STAT_DOS_FLAGS
598 bool attributes_changed
;
600 if (set_stat_dos_flags(conn
, fname
, st
, dosmode
,
601 &attributes_changed
))
603 if (!newfile
&& attributes_changed
) {
604 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
605 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
607 st
->st_ex_mode
= unixmode
;
613 /* Store the DOS attributes in an EA by preference. */
614 if (set_ea_dos_attribute(conn
, fname
, st
, dosmode
)) {
616 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
617 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
619 st
->st_ex_mode
= unixmode
;
623 unixmode
= unix_mode(conn
,dosmode
,fname
, parent_dir
);
625 /* preserve the s bits */
626 mask
|= (S_ISUID
| S_ISGID
);
628 /* preserve the t bit */
633 /* possibly preserve the x bits */
634 if (!MAP_ARCHIVE(conn
))
636 if (!MAP_SYSTEM(conn
))
638 if (!MAP_HIDDEN(conn
))
641 unixmode
|= (st
->st_ex_mode
& mask
);
643 /* if we previously had any r bits set then leave them alone */
644 if ((tmp
= st
->st_ex_mode
& (S_IRUSR
|S_IRGRP
|S_IROTH
))) {
645 unixmode
&= ~(S_IRUSR
|S_IRGRP
|S_IROTH
);
649 /* if we previously had any w bits set then leave them alone
650 whilst adding in the new w bits, if the new mode is not rdonly */
651 if (!IS_DOS_READONLY(dosmode
)) {
652 unixmode
|= (st
->st_ex_mode
& (S_IWUSR
|S_IWGRP
|S_IWOTH
));
655 ret
= SMB_VFS_CHMOD(conn
, fname
, unixmode
);
657 if(!newfile
|| (lret
!= -1)) {
658 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
659 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
661 st
->st_ex_mode
= unixmode
;
665 if((errno
!= EPERM
) && (errno
!= EACCES
))
668 if(!lp_dos_filemode(SNUM(conn
)))
671 /* We want DOS semantics, ie allow non owner with write permission to change the
672 bits on a file. Just like file_ntimes below.
675 /* Check if we have write access. */
676 if (CAN_WRITE(conn
)) {
678 * We need to open the file with write access whilst
679 * still in our current user context. This ensures we
680 * are not violating security in doing the fchmod.
681 * This file open does *not* break any oplocks we are
682 * holding. We need to review this.... may need to
683 * break batch oplocks open by others. JRA.
686 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL
, conn
, fname
, st
,
690 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
692 close_file_fchmod(NULL
, fsp
);
694 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
695 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
698 st
->st_ex_mode
= unixmode
;
705 /*******************************************************************
706 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
708 *******************************************************************/
710 int file_ntimes(connection_struct
*conn
, const char *fname
,
711 struct smb_file_time
*ft
)
713 SMB_STRUCT_STAT sbuf
;
719 DEBUG(6, ("file_ntime: actime: %s",
720 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
721 DEBUG(6, ("file_ntime: modtime: %s",
722 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
723 DEBUG(6, ("file_ntime: createtime: %s",
724 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
726 /* Don't update the time on read-only shares */
727 /* We need this as set_filetime (which can be called on
728 close and other paths) can end up calling this function
729 without the NEED_WRITE protection. Found by :
730 Leo Weppelman <leo@wau.mis.ah.nl>
733 if (!CAN_WRITE(conn
)) {
737 if(SMB_VFS_NTIMES(conn
, fname
, ft
) == 0) {
741 if((errno
!= EPERM
) && (errno
!= EACCES
)) {
745 if(!lp_dos_filetimes(SNUM(conn
))) {
749 /* We have permission (given by the Samba admin) to
750 break POSIX semantics and allow a user to change
751 the time on a file they don't own but can write to
755 /* Check if we have write access. */
756 if (can_write_to_file(conn
, fname
, &sbuf
)) {
757 /* We are allowed to become root and change the filetime. */
759 ret
= SMB_VFS_NTIMES(conn
, fname
, ft
);
766 /******************************************************************
767 Force a "sticky" write time on a pathname. This will always be
768 returned on all future write time queries and set on close.
769 ******************************************************************/
771 bool set_sticky_write_time_path(connection_struct
*conn
, const char *fname
,
772 struct file_id fileid
, const struct timespec mtime
)
774 if (null_timespec(mtime
)) {
778 if (!set_sticky_write_time(fileid
, mtime
)) {
785 /******************************************************************
786 Force a "sticky" write time on an fsp. This will always be
787 returned on all future write time queries and set on close.
788 ******************************************************************/
790 bool set_sticky_write_time_fsp(struct files_struct
*fsp
, const struct timespec mtime
)
792 fsp
->write_time_forced
= true;
793 TALLOC_FREE(fsp
->update_write_time_event
);
795 return set_sticky_write_time_path(fsp
->conn
, fsp
->fsp_name
,
796 fsp
->file_id
, mtime
);
799 /******************************************************************
800 Update a write time immediately, without the 2 second delay.
801 ******************************************************************/
803 bool update_write_time(struct files_struct
*fsp
)
805 if (!set_write_time(fsp
->file_id
, timespec_current())) {
809 notify_fname(fsp
->conn
, NOTIFY_ACTION_MODIFIED
,
810 FILE_NOTIFY_CHANGE_LAST_WRITE
, fsp
->fsp_name
);