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 extern enum protocol_types Protocol
;
25 static uint32_t filter_mode_by_protocol(uint32_t mode
)
27 if (Protocol
<= PROTOCOL_LANMAN2
) {
28 DEBUG(10,("filter_mode_by_protocol: "
29 "filtering result 0x%x to 0x%x\n",
31 (unsigned int)(mode
& 0x3f) ));
37 static int set_sparse_flag(const SMB_STRUCT_STAT
* const sbuf
)
39 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
40 if (sbuf
->st_size
> sbuf
->st_blocks
* (SMB_OFF_T
)STAT_ST_BLOCKSIZE
) {
41 return FILE_ATTRIBUTE_SPARSE
;
47 static int set_link_read_only_flag(const SMB_STRUCT_STAT
*const sbuf
)
51 if (S_ISLNK(sbuf
->st_mode
) && S_ISDIR(sbuf
->st_mode
))
58 /****************************************************************************
59 Change a dos mode to a unix mode.
60 Base permission for files:
61 if creating file and inheriting (i.e. parent_dir != NULL)
62 apply read/write bits from parent directory.
64 everybody gets read bit set
65 dos readonly is represented in unix by removing everyone's write bit
66 dos archive is represented in unix by the user's execute bit
67 dos system is represented in unix by the group's execute bit
68 dos hidden is represented in unix by the other's execute bit
70 Then apply create mask,
73 Base permission for directories:
74 dos directory is represented in unix by unix's dir bit and the exec bit
76 Then apply create mask,
79 ****************************************************************************/
81 mode_t
unix_mode(connection_struct
*conn
, int dosmode
, const char *fname
,
82 const char *inherit_from_dir
)
84 mode_t result
= (S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
);
85 mode_t dir_mode
= 0; /* Mode of the inherit_from directory if
88 if (!lp_store_dos_attributes(SNUM(conn
)) && IS_DOS_READONLY(dosmode
)) {
89 result
&= ~(S_IWUSR
| S_IWGRP
| S_IWOTH
);
92 if (fname
&& (inherit_from_dir
!= NULL
)
93 && lp_inherit_perms(SNUM(conn
))) {
96 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname
,
98 if (SMB_VFS_STAT(conn
, inherit_from_dir
, &sbuf
) != 0) {
99 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname
,
100 inherit_from_dir
, strerror(errno
)));
101 return(0); /* *** shouldn't happen! *** */
104 /* Save for later - but explicitly remove setuid bit for safety. */
105 dir_mode
= sbuf
.st_mode
& ~S_ISUID
;
106 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname
,(int)dir_mode
));
111 if (IS_DOS_DIR(dosmode
)) {
112 /* We never make directories read only for the owner as under DOS a user
113 can always create a file in a read-only directory. */
114 result
|= (S_IFDIR
| S_IWUSR
);
117 /* Inherit mode of parent directory. */
120 /* Provisionally add all 'x' bits */
121 result
|= (S_IXUSR
| S_IXGRP
| S_IXOTH
);
123 /* Apply directory mask */
124 result
&= lp_dir_mask(SNUM(conn
));
125 /* Add in force bits */
126 result
|= lp_force_dir_mode(SNUM(conn
));
129 if (lp_map_archive(SNUM(conn
)) && IS_DOS_ARCHIVE(dosmode
))
132 if (lp_map_system(SNUM(conn
)) && IS_DOS_SYSTEM(dosmode
))
135 if (lp_map_hidden(SNUM(conn
)) && IS_DOS_HIDDEN(dosmode
))
139 /* Inherit 666 component of parent directory mode */
140 result
|= dir_mode
& (S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
);
142 /* Apply mode mask */
143 result
&= lp_create_mask(SNUM(conn
));
144 /* Add in force bits */
145 result
|= lp_force_create_mode(SNUM(conn
));
149 DEBUG(3,("unix_mode(%s) returning 0%o\n",fname
,(int)result
));
153 /****************************************************************************
154 Change a unix mode to a dos mode.
155 ****************************************************************************/
157 static uint32
dos_mode_from_sbuf(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
)
160 enum mapreadonly_options ro_opts
= (enum mapreadonly_options
)lp_map_readonly(SNUM(conn
));
162 if (ro_opts
== MAP_READONLY_YES
) {
163 /* Original Samba method - map inverse of user "w" bit. */
164 if ((sbuf
->st_mode
& S_IWUSR
) == 0) {
167 } else if (ro_opts
== MAP_READONLY_PERMISSIONS
) {
168 /* Check actual permissions for read-only. */
169 if (!can_write_to_file(conn
, path
, sbuf
)) {
172 } /* Else never set the readonly bit. */
174 if (MAP_ARCHIVE(conn
) && ((sbuf
->st_mode
& S_IXUSR
) != 0))
177 if (MAP_SYSTEM(conn
) && ((sbuf
->st_mode
& S_IXGRP
) != 0))
180 if (MAP_HIDDEN(conn
) && ((sbuf
->st_mode
& S_IXOTH
) != 0))
183 if (S_ISDIR(sbuf
->st_mode
))
184 result
= aDIR
| (result
& aRONLY
);
186 result
|= set_sparse_flag(sbuf
);
187 result
|= set_link_read_only_flag(sbuf
);
189 DEBUG(8,("dos_mode_from_sbuf returning "));
191 if (result
& aHIDDEN
) DEBUG(8, ("h"));
192 if (result
& aRONLY
) DEBUG(8, ("r"));
193 if (result
& aSYSTEM
) DEBUG(8, ("s"));
194 if (result
& aDIR
) DEBUG(8, ("d"));
195 if (result
& aARCH
) DEBUG(8, ("a"));
201 /****************************************************************************
202 Get DOS attributes from an EA.
203 ****************************************************************************/
205 static bool get_ea_dos_attribute(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
, uint32
*pattr
)
209 unsigned int dosattr
;
211 if (!lp_store_dos_attributes(SNUM(conn
))) {
215 /* Don't reset pattr to zero as we may already have filename-based attributes we
218 sizeret
= SMB_VFS_GETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, sizeof(attrstr
));
222 || errno
== ENOTSUP
) {
226 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
227 path
, strerror(errno
) ));
228 set_store_dos_attributes(SNUM(conn
), False
);
232 /* Null terminate string. */
233 attrstr
[sizeret
] = 0;
234 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path
, attrstr
));
236 if (sizeret
< 2 || attrstr
[0] != '0' || attrstr
[1] != 'x' ||
237 sscanf(attrstr
, "%x", &dosattr
) != 1) {
238 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path
, attrstr
));
242 if (S_ISDIR(sbuf
->st_mode
)) {
245 *pattr
= (uint32
)(dosattr
& SAMBA_ATTRIBUTES_MASK
);
247 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr
));
249 if (dosattr
& aHIDDEN
) DEBUG(8, ("h"));
250 if (dosattr
& aRONLY
) DEBUG(8, ("r"));
251 if (dosattr
& aSYSTEM
) DEBUG(8, ("s"));
252 if (dosattr
& aDIR
) DEBUG(8, ("d"));
253 if (dosattr
& aARCH
) DEBUG(8, ("a"));
260 /****************************************************************************
261 Set DOS attributes in an EA.
262 ****************************************************************************/
264 static bool set_ea_dos_attribute(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
, uint32 dosmode
)
267 files_struct
*fsp
= NULL
;
270 if (!lp_store_dos_attributes(SNUM(conn
))) {
274 snprintf(attrstr
, sizeof(attrstr
)-1, "0x%x", dosmode
& SAMBA_ATTRIBUTES_MASK
);
275 if (SMB_VFS_SETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, strlen(attrstr
), 0) == -1) {
276 if((errno
!= EPERM
) && (errno
!= EACCES
)) {
279 || errno
== ENOTSUP
) {
283 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
284 path
, strerror(errno
) ));
285 set_store_dos_attributes(SNUM(conn
), False
);
290 /* We want DOS semantics, ie allow non owner with write permission to change the
291 bits on a file. Just like file_ntimes below.
294 /* Check if we have write access. */
295 if(!CAN_WRITE(conn
) || !lp_dos_filemode(SNUM(conn
)))
299 * We need to open the file with write access whilst
300 * still in our current user context. This ensures we
301 * are not violating security in doing the setxattr.
304 if (!NT_STATUS_IS_OK(open_file_fchmod(conn
, path
, sbuf
,
308 if (SMB_VFS_SETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, strlen(attrstr
), 0) == 0) {
312 close_file(NULL
, fsp
, NORMAL_CLOSE
);
315 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr
, path
));
319 /****************************************************************************
320 Change a unix mode to a dos mode for an ms dfs link.
321 ****************************************************************************/
323 uint32
dos_mode_msdfs(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
)
327 DEBUG(8,("dos_mode_msdfs: %s\n", path
));
329 if (!VALID_STAT(*sbuf
)) {
333 /* First do any modifications that depend on the path name. */
334 /* hide files with a name starting with a . */
335 if (lp_hide_dot_files(SNUM(conn
))) {
336 const char *p
= strrchr_m(path
,'/');
343 /* Only . and .. are not hidden. */
344 if (p
[0] == '.' && !((p
[1] == '\0') ||
345 (p
[1] == '.' && p
[2] == '\0'))) {
350 result
|= dos_mode_from_sbuf(conn
, path
, sbuf
);
352 /* Optimization : Only call is_hidden_path if it's not already
354 if (!(result
& aHIDDEN
) && IS_HIDDEN_PATH(conn
,path
)) {
359 result
= FILE_ATTRIBUTE_NORMAL
;
362 result
= filter_mode_by_protocol(result
);
364 DEBUG(8,("dos_mode_msdfs returning "));
366 if (result
& aHIDDEN
) DEBUG(8, ("h"));
367 if (result
& aRONLY
) DEBUG(8, ("r"));
368 if (result
& aSYSTEM
) DEBUG(8, ("s"));
369 if (result
& aDIR
) DEBUG(8, ("d"));
370 if (result
& aARCH
) DEBUG(8, ("a"));
371 if (result
& FILE_ATTRIBUTE_SPARSE
) DEBUG(8, ("[sparse]"));
378 #ifdef HAVE_STAT_DOS_FLAGS
379 /****************************************************************************
380 Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*)
381 ****************************************************************************/
383 int dos_attributes_to_stat_dos_flags(uint32_t dosmode
)
385 uint32_t dos_stat_flags
= 0;
388 dos_stat_flags
|= UF_DOS_ARCHIVE
;
389 if (dosmode
& aHIDDEN
)
390 dos_stat_flags
|= UF_DOS_HIDDEN
;
391 if (dosmode
& aRONLY
)
392 dos_stat_flags
|= UF_DOS_RO
;
393 if (dosmode
& aSYSTEM
)
394 dos_stat_flags
|= UF_DOS_SYSTEM
;
395 if (dosmode
& FILE_ATTRIBUTE_NONINDEXED
)
396 dos_stat_flags
|= UF_DOS_NOINDEX
;
398 return dos_stat_flags
;
401 /****************************************************************************
402 Gets DOS attributes, accessed via st_flags in the stat struct.
403 ****************************************************************************/
405 static bool get_stat_dos_flags(connection_struct
*conn
,
407 const SMB_STRUCT_STAT
*sbuf
,
410 SMB_ASSERT(sbuf
&& VALID_STAT(*sbuf
));
413 if (!lp_store_dos_attributes(SNUM(conn
))) {
417 DEBUG(5, ("Getting stat dos attributes for %s.\n", fname
));
419 if (sbuf
->st_flags
& UF_DOS_ARCHIVE
)
421 if (sbuf
->st_flags
& UF_DOS_HIDDEN
)
423 if (sbuf
->st_flags
& UF_DOS_RO
)
425 if (sbuf
->st_flags
& UF_DOS_SYSTEM
)
427 if (sbuf
->st_flags
& UF_DOS_NOINDEX
)
428 *dosmode
|= FILE_ATTRIBUTE_NONINDEXED
;
429 if (S_ISDIR(sbuf
->st_mode
))
432 *dosmode
|= set_sparse_flag(sbuf
);
433 *dosmode
|= set_link_read_only_flag(sbuf
);
438 /****************************************************************************
439 Sets DOS attributes, stored in st_flags of the inode.
440 ****************************************************************************/
442 static bool set_stat_dos_flags(connection_struct
*conn
,
444 SMB_STRUCT_STAT
*sbuf
,
446 bool *attributes_changed
)
448 uint32_t new_flags
= 0;
451 SMB_ASSERT(sbuf
&& VALID_STAT(*sbuf
));
452 SMB_ASSERT(attributes_changed
);
454 *attributes_changed
= false;
456 if (!lp_store_dos_attributes(SNUM(conn
))) {
460 DEBUG(5, ("Setting stat dos attributes for %s.\n", fname
));
462 new_flags
= (sbuf
->st_flags
& ~UF_DOS_FLAGS
) |
463 dos_attributes_to_stat_dos_flags(dosmode
);
465 /* Return early if no flags changed. */
466 if (new_flags
== sbuf
->st_flags
)
469 DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags
,
472 /* Set new flags with chflags. */
473 error
= SMB_VFS_CHFLAGS(conn
, fname
, new_flags
);
475 DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
476 "file %s! errno=%d\n", new_flags
, fname
, errno
));
480 *attributes_changed
= true;
483 #endif /* HAVE_STAT_DOS_FLAGS */
485 /****************************************************************************
486 Change a unix mode to a dos mode.
487 ****************************************************************************/
489 uint32
dos_mode(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
)
492 bool offline
, used_stat_dos_flags
= false;
494 DEBUG(8,("dos_mode: %s\n", path
));
496 if (!VALID_STAT(*sbuf
)) {
500 /* First do any modifications that depend on the path name. */
501 /* hide files with a name starting with a . */
502 if (lp_hide_dot_files(SNUM(conn
))) {
503 const char *p
= strrchr_m(path
,'/');
510 /* Only . and .. are not hidden. */
511 if (p
[0] == '.' && !((p
[1] == '\0') ||
512 (p
[1] == '.' && p
[2] == '\0'))) {
517 #ifdef HAVE_STAT_DOS_FLAGS
518 used_stat_dos_flags
= get_stat_dos_flags(conn
, path
, sbuf
, &result
);
520 if (!used_stat_dos_flags
) {
521 /* Get the DOS attributes from an EA by preference. */
522 if (get_ea_dos_attribute(conn
, path
, sbuf
, &result
)) {
523 result
|= set_sparse_flag(sbuf
);
525 result
|= dos_mode_from_sbuf(conn
, path
, sbuf
);
530 offline
= SMB_VFS_IS_OFFLINE(conn
, path
, sbuf
);
531 if (S_ISREG(sbuf
->st_mode
) && offline
) {
532 result
|= FILE_ATTRIBUTE_OFFLINE
;
535 /* Optimization : Only call is_hidden_path if it's not already
537 if (!(result
& aHIDDEN
) && IS_HIDDEN_PATH(conn
,path
)) {
542 result
= FILE_ATTRIBUTE_NORMAL
;
545 result
= filter_mode_by_protocol(result
);
547 DEBUG(8,("dos_mode returning "));
549 if (result
& aHIDDEN
) DEBUG(8, ("h"));
550 if (result
& aRONLY
) DEBUG(8, ("r"));
551 if (result
& aSYSTEM
) DEBUG(8, ("s"));
552 if (result
& aDIR
) DEBUG(8, ("d"));
553 if (result
& aARCH
) DEBUG(8, ("a"));
554 if (result
& FILE_ATTRIBUTE_SPARSE
) DEBUG(8, ("[sparse]"));
561 /*******************************************************************
562 chmod a file - but preserve some bits.
563 ********************************************************************/
565 int file_set_dosmode(connection_struct
*conn
, const char *fname
,
566 uint32 dosmode
, SMB_STRUCT_STAT
*st
,
567 const char *parent_dir
,
574 int ret
= -1, lret
= -1;
577 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
578 dosmode
&= (SAMBA_ATTRIBUTES_MASK
| FILE_ATTRIBUTE_OFFLINE
);
580 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode
, fname
));
583 SET_STAT_INVALID(st1
);
587 if (!VALID_STAT(*st
)) {
588 if (SMB_VFS_STAT(conn
,fname
,st
))
592 unixmode
= st
->st_mode
;
594 get_acl_group_bits(conn
, fname
, &st
->st_mode
);
596 if (S_ISDIR(st
->st_mode
))
601 old_mode
= dos_mode(conn
,fname
,st
);
603 if (dosmode
& FILE_ATTRIBUTE_OFFLINE
) {
604 if (!(old_mode
& FILE_ATTRIBUTE_OFFLINE
)) {
605 lret
= SMB_VFS_SET_OFFLINE(conn
, fname
);
607 DEBUG(0, ("set_dos_mode: client has asked to set "
608 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
609 "an error while setting it or it is not supported.\n",
615 dosmode
&= ~FILE_ATTRIBUTE_OFFLINE
;
616 old_mode
&= ~FILE_ATTRIBUTE_OFFLINE
;
618 if (old_mode
== dosmode
) {
619 st
->st_mode
= unixmode
;
623 #ifdef HAVE_STAT_DOS_FLAGS
625 bool attributes_changed
;
627 if (set_stat_dos_flags(conn
, fname
, st
, dosmode
,
628 &attributes_changed
))
630 if (!newfile
&& attributes_changed
) {
631 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
632 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
634 st
->st_mode
= unixmode
;
640 /* Store the DOS attributes in an EA by preference. */
641 if (set_ea_dos_attribute(conn
, fname
, st
, dosmode
)) {
643 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
644 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
646 st
->st_mode
= unixmode
;
650 unixmode
= unix_mode(conn
,dosmode
,fname
, parent_dir
);
652 /* preserve the s bits */
653 mask
|= (S_ISUID
| S_ISGID
);
655 /* preserve the t bit */
660 /* possibly preserve the x bits */
661 if (!MAP_ARCHIVE(conn
))
663 if (!MAP_SYSTEM(conn
))
665 if (!MAP_HIDDEN(conn
))
668 unixmode
|= (st
->st_mode
& mask
);
670 /* if we previously had any r bits set then leave them alone */
671 if ((tmp
= st
->st_mode
& (S_IRUSR
|S_IRGRP
|S_IROTH
))) {
672 unixmode
&= ~(S_IRUSR
|S_IRGRP
|S_IROTH
);
676 /* if we previously had any w bits set then leave them alone
677 whilst adding in the new w bits, if the new mode is not rdonly */
678 if (!IS_DOS_READONLY(dosmode
)) {
679 unixmode
|= (st
->st_mode
& (S_IWUSR
|S_IWGRP
|S_IWOTH
));
682 ret
= SMB_VFS_CHMOD(conn
, fname
, unixmode
);
684 if(!newfile
|| (lret
!= -1)) {
685 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
686 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
688 st
->st_mode
= unixmode
;
692 if((errno
!= EPERM
) && (errno
!= EACCES
))
695 if(!lp_dos_filemode(SNUM(conn
)))
698 /* We want DOS semantics, ie allow non owner with write permission to change the
699 bits on a file. Just like file_ntimes below.
702 /* Check if we have write access. */
703 if (CAN_WRITE(conn
)) {
705 * We need to open the file with write access whilst
706 * still in our current user context. This ensures we
707 * are not violating security in doing the fchmod.
710 if (!NT_STATUS_IS_OK(open_file_fchmod(conn
, fname
, st
,
714 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
716 close_file(NULL
, fsp
, NORMAL_CLOSE
);
718 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
719 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
722 st
->st_mode
= unixmode
;
729 /*******************************************************************
730 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
732 *******************************************************************/
734 int file_ntimes(connection_struct
*conn
, const char *fname
,
735 struct smb_file_time
*ft
)
737 SMB_STRUCT_STAT sbuf
;
743 DEBUG(6, ("file_ntime: actime: %s",
744 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
745 DEBUG(6, ("file_ntime: modtime: %s",
746 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
747 DEBUG(6, ("file_ntime: createtime: %s",
748 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
750 /* Don't update the time on read-only shares */
751 /* We need this as set_filetime (which can be called on
752 close and other paths) can end up calling this function
753 without the NEED_WRITE protection. Found by :
754 Leo Weppelman <leo@wau.mis.ah.nl>
757 if (!CAN_WRITE(conn
)) {
761 if(SMB_VFS_NTIMES(conn
, fname
, ft
) == 0) {
765 if((errno
!= EPERM
) && (errno
!= EACCES
)) {
769 if(!lp_dos_filetimes(SNUM(conn
))) {
773 /* We have permission (given by the Samba admin) to
774 break POSIX semantics and allow a user to change
775 the time on a file they don't own but can write to
779 /* Check if we have write access. */
780 if (can_write_to_file(conn
, fname
, &sbuf
)) {
781 /* We are allowed to become root and change the filetime. */
783 ret
= SMB_VFS_NTIMES(conn
, fname
, ft
);
790 /******************************************************************
791 Force a "sticky" write time on a pathname. This will always be
792 returned on all future write time queries and set on close.
793 ******************************************************************/
795 bool set_sticky_write_time_path(connection_struct
*conn
, const char *fname
,
796 struct file_id fileid
, const struct timespec mtime
)
798 if (null_timespec(mtime
)) {
802 if (!set_sticky_write_time(fileid
, mtime
)) {
809 /******************************************************************
810 Force a "sticky" write time on an fsp. This will always be
811 returned on all future write time queries and set on close.
812 ******************************************************************/
814 bool set_sticky_write_time_fsp(struct files_struct
*fsp
, const struct timespec mtime
)
816 fsp
->write_time_forced
= true;
817 TALLOC_FREE(fsp
->update_write_time_event
);
819 return set_sticky_write_time_path(fsp
->conn
, fsp
->fsp_name
,
820 fsp
->file_id
, mtime
);
823 /******************************************************************
824 Update a write time immediately, without the 2 second delay.
825 ******************************************************************/
827 bool update_write_time(struct files_struct
*fsp
)
829 if (!set_write_time(fsp
->file_id
, timespec_current())) {
833 notify_fname(fsp
->conn
, NOTIFY_ACTION_MODIFIED
,
834 FILE_NOTIFY_CHANGE_LAST_WRITE
, fsp
->fsp_name
);