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 int set_sparse_flag(const SMB_STRUCT_STAT
* const sbuf
)
27 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
28 if (sbuf
->st_size
> sbuf
->st_blocks
* (SMB_OFF_T
)STAT_ST_BLOCKSIZE
) {
29 return FILE_ATTRIBUTE_SPARSE
;
35 static int set_link_read_only_flag(const SMB_STRUCT_STAT
*const sbuf
)
39 if (S_ISLNK(sbuf
->st_mode
) && S_ISDIR(sbuf
->st_mode
))
46 /****************************************************************************
47 Change a dos mode to a unix mode.
48 Base permission for files:
49 if creating file and inheriting (i.e. parent_dir != NULL)
50 apply read/write bits from parent directory.
52 everybody gets read bit set
53 dos readonly is represented in unix by removing everyone's write bit
54 dos archive is represented in unix by the user's execute bit
55 dos system is represented in unix by the group's execute bit
56 dos hidden is represented in unix by the other's execute bit
58 Then apply create mask,
61 Base permission for directories:
62 dos directory is represented in unix by unix's dir bit and the exec bit
64 Then apply create mask,
67 ****************************************************************************/
69 mode_t
unix_mode(connection_struct
*conn
, int dosmode
, const char *fname
,
70 const char *inherit_from_dir
)
72 mode_t result
= (S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
);
73 mode_t dir_mode
= 0; /* Mode of the inherit_from directory if
76 if (!lp_store_dos_attributes(SNUM(conn
)) && IS_DOS_READONLY(dosmode
)) {
77 result
&= ~(S_IWUSR
| S_IWGRP
| S_IWOTH
);
80 if (fname
&& (inherit_from_dir
!= NULL
)
81 && lp_inherit_perms(SNUM(conn
))) {
84 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname
,
86 if (SMB_VFS_STAT(conn
, inherit_from_dir
, &sbuf
) != 0) {
87 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname
,
88 inherit_from_dir
, strerror(errno
)));
89 return(0); /* *** shouldn't happen! *** */
92 /* Save for later - but explicitly remove setuid bit for safety. */
93 dir_mode
= sbuf
.st_mode
& ~S_ISUID
;
94 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname
,(int)dir_mode
));
99 if (IS_DOS_DIR(dosmode
)) {
100 /* We never make directories read only for the owner as under DOS a user
101 can always create a file in a read-only directory. */
102 result
|= (S_IFDIR
| S_IWUSR
);
105 /* Inherit mode of parent directory. */
108 /* Provisionally add all 'x' bits */
109 result
|= (S_IXUSR
| S_IXGRP
| S_IXOTH
);
111 /* Apply directory mask */
112 result
&= lp_dir_mask(SNUM(conn
));
113 /* Add in force bits */
114 result
|= lp_force_dir_mode(SNUM(conn
));
117 if (lp_map_archive(SNUM(conn
)) && IS_DOS_ARCHIVE(dosmode
))
120 if (lp_map_system(SNUM(conn
)) && IS_DOS_SYSTEM(dosmode
))
123 if (lp_map_hidden(SNUM(conn
)) && IS_DOS_HIDDEN(dosmode
))
127 /* Inherit 666 component of parent directory mode */
128 result
|= dir_mode
& (S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
);
130 /* Apply mode mask */
131 result
&= lp_create_mask(SNUM(conn
));
132 /* Add in force bits */
133 result
|= lp_force_create_mode(SNUM(conn
));
137 DEBUG(3,("unix_mode(%s) returning 0%o\n",fname
,(int)result
));
141 /****************************************************************************
142 Change a unix mode to a dos mode.
143 ****************************************************************************/
145 static uint32
dos_mode_from_sbuf(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
)
148 enum mapreadonly_options ro_opts
= (enum mapreadonly_options
)lp_map_readonly(SNUM(conn
));
150 if (ro_opts
== MAP_READONLY_YES
) {
151 /* Original Samba method - map inverse of user "w" bit. */
152 if ((sbuf
->st_mode
& S_IWUSR
) == 0) {
155 } else if (ro_opts
== MAP_READONLY_PERMISSIONS
) {
156 /* Check actual permissions for read-only. */
157 if (!can_write_to_file(conn
, path
, sbuf
)) {
160 } /* Else never set the readonly bit. */
162 if (MAP_ARCHIVE(conn
) && ((sbuf
->st_mode
& S_IXUSR
) != 0))
165 if (MAP_SYSTEM(conn
) && ((sbuf
->st_mode
& S_IXGRP
) != 0))
168 if (MAP_HIDDEN(conn
) && ((sbuf
->st_mode
& S_IXOTH
) != 0))
171 if (S_ISDIR(sbuf
->st_mode
))
172 result
= aDIR
| (result
& aRONLY
);
174 result
|= set_sparse_flag(sbuf
);
175 result
|= set_link_read_only_flag(sbuf
);
177 DEBUG(8,("dos_mode_from_sbuf returning "));
179 if (result
& aHIDDEN
) DEBUG(8, ("h"));
180 if (result
& aRONLY
) DEBUG(8, ("r"));
181 if (result
& aSYSTEM
) DEBUG(8, ("s"));
182 if (result
& aDIR
) DEBUG(8, ("d"));
183 if (result
& aARCH
) DEBUG(8, ("a"));
189 /****************************************************************************
190 Get DOS attributes from an EA.
191 ****************************************************************************/
193 static bool get_ea_dos_attribute(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
, uint32
*pattr
)
197 unsigned int dosattr
;
199 if (!lp_store_dos_attributes(SNUM(conn
))) {
203 /* Don't reset pattr to zero as we may already have filename-based attributes we
206 sizeret
= SMB_VFS_GETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, sizeof(attrstr
));
210 || errno
== ENOTSUP
) {
214 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
215 path
, strerror(errno
) ));
216 set_store_dos_attributes(SNUM(conn
), False
);
220 /* Null terminate string. */
221 attrstr
[sizeret
] = 0;
222 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path
, attrstr
));
224 if (sizeret
< 2 || attrstr
[0] != '0' || attrstr
[1] != 'x' ||
225 sscanf(attrstr
, "%x", &dosattr
) != 1) {
226 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path
, attrstr
));
230 if (S_ISDIR(sbuf
->st_mode
)) {
233 *pattr
= (uint32
)(dosattr
& SAMBA_ATTRIBUTES_MASK
);
235 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr
));
237 if (dosattr
& aHIDDEN
) DEBUG(8, ("h"));
238 if (dosattr
& aRONLY
) DEBUG(8, ("r"));
239 if (dosattr
& aSYSTEM
) DEBUG(8, ("s"));
240 if (dosattr
& aDIR
) DEBUG(8, ("d"));
241 if (dosattr
& aARCH
) DEBUG(8, ("a"));
248 /****************************************************************************
249 Set DOS attributes in an EA.
250 ****************************************************************************/
252 static bool set_ea_dos_attribute(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
, uint32 dosmode
)
255 files_struct
*fsp
= NULL
;
258 if (!lp_store_dos_attributes(SNUM(conn
))) {
262 snprintf(attrstr
, sizeof(attrstr
)-1, "0x%x", dosmode
& SAMBA_ATTRIBUTES_MASK
);
263 if (SMB_VFS_SETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, strlen(attrstr
), 0) == -1) {
264 if((errno
!= EPERM
) && (errno
!= EACCES
)) {
267 || errno
== ENOTSUP
) {
271 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
272 path
, strerror(errno
) ));
273 set_store_dos_attributes(SNUM(conn
), False
);
278 /* We want DOS semantics, ie allow non owner with write permission to change the
279 bits on a file. Just like file_ntimes below.
282 /* Check if we have write access. */
283 if(!CAN_WRITE(conn
) || !lp_dos_filemode(SNUM(conn
)))
287 * We need to open the file with write access whilst
288 * still in our current user context. This ensures we
289 * are not violating security in doing the setxattr.
292 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL
, conn
, path
, sbuf
,
296 if (SMB_VFS_SETXATTR(conn
, path
, SAMBA_XATTR_DOS_ATTRIB
, attrstr
, strlen(attrstr
), 0) == 0) {
300 close_file_fchmod(NULL
, fsp
);
303 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr
, path
));
307 /****************************************************************************
308 Change a unix mode to a dos mode for an ms dfs link.
309 ****************************************************************************/
311 uint32
dos_mode_msdfs(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
)
315 DEBUG(8,("dos_mode_msdfs: %s\n", path
));
317 if (!VALID_STAT(*sbuf
)) {
321 /* First do any modifications that depend on the path name. */
322 /* hide files with a name starting with a . */
323 if (lp_hide_dot_files(SNUM(conn
))) {
324 const char *p
= strrchr_m(path
,'/');
331 /* Only . and .. are not hidden. */
332 if (p
[0] == '.' && !((p
[1] == '\0') ||
333 (p
[1] == '.' && p
[2] == '\0'))) {
338 result
|= dos_mode_from_sbuf(conn
, path
, sbuf
);
340 /* Optimization : Only call is_hidden_path if it's not already
342 if (!(result
& aHIDDEN
) && IS_HIDDEN_PATH(conn
,path
)) {
346 if (Protocol
<= PROTOCOL_LANMAN2
) {
347 DEBUG(10,("dos_mode_msdfs : filtering result 0x%x\n",
348 (unsigned int)result
));
352 DEBUG(8,("dos_mode_msdfs returning "));
354 if (result
& aHIDDEN
) DEBUG(8, ("h"));
355 if (result
& aRONLY
) DEBUG(8, ("r"));
356 if (result
& aSYSTEM
) DEBUG(8, ("s"));
357 if (result
& aDIR
) DEBUG(8, ("d"));
358 if (result
& aARCH
) DEBUG(8, ("a"));
359 if (result
& FILE_ATTRIBUTE_SPARSE
) DEBUG(8, ("[sparse]"));
366 #ifdef HAVE_STAT_DOS_FLAGS
367 /****************************************************************************
368 Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*)
369 ****************************************************************************/
371 int dos_attributes_to_stat_dos_flags(uint32_t dosmode
)
373 uint32_t dos_stat_flags
= 0;
376 dos_stat_flags
|= UF_DOS_ARCHIVE
;
377 if (dosmode
& aHIDDEN
)
378 dos_stat_flags
|= UF_DOS_HIDDEN
;
379 if (dosmode
& aRONLY
)
380 dos_stat_flags
|= UF_DOS_RO
;
381 if (dosmode
& aSYSTEM
)
382 dos_stat_flags
|= UF_DOS_SYSTEM
;
383 if (dosmode
& FILE_ATTRIBUTE_NONINDEXED
)
384 dos_stat_flags
|= UF_DOS_NOINDEX
;
386 return dos_stat_flags
;
389 /****************************************************************************
390 Gets DOS attributes, accessed via st_flags in the stat struct.
391 ****************************************************************************/
393 static bool get_stat_dos_flags(connection_struct
*conn
,
395 const SMB_STRUCT_STAT
*sbuf
,
398 SMB_ASSERT(sbuf
&& VALID_STAT(*sbuf
));
401 if (!lp_store_dos_attributes(SNUM(conn
))) {
405 DEBUG(5, ("Getting stat dos attributes for %s.\n", fname
));
407 if (sbuf
->st_flags
& UF_DOS_ARCHIVE
)
409 if (sbuf
->st_flags
& UF_DOS_HIDDEN
)
411 if (sbuf
->st_flags
& UF_DOS_RO
)
413 if (sbuf
->st_flags
& UF_DOS_SYSTEM
)
415 if (sbuf
->st_flags
& UF_DOS_NOINDEX
)
416 *dosmode
|= FILE_ATTRIBUTE_NONINDEXED
;
417 if (S_ISDIR(sbuf
->st_mode
))
420 *dosmode
|= set_sparse_flag(sbuf
);
421 *dosmode
|= set_link_read_only_flag(sbuf
);
426 /****************************************************************************
427 Sets DOS attributes, stored in st_flags of the inode.
428 ****************************************************************************/
430 static bool set_stat_dos_flags(connection_struct
*conn
,
432 SMB_STRUCT_STAT
*sbuf
,
434 bool *attributes_changed
)
436 uint32_t new_flags
= 0;
439 SMB_ASSERT(sbuf
&& VALID_STAT(*sbuf
));
440 SMB_ASSERT(attributes_changed
);
442 *attributes_changed
= false;
444 if (!lp_store_dos_attributes(SNUM(conn
))) {
448 DEBUG(5, ("Setting stat dos attributes for %s.\n", fname
));
450 new_flags
= (sbuf
->st_flags
& ~UF_DOS_FLAGS
) |
451 dos_attributes_to_stat_dos_flags(dosmode
);
453 /* Return early if no flags changed. */
454 if (new_flags
== sbuf
->st_flags
)
457 DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags
,
460 /* Set new flags with chflags. */
461 error
= SMB_VFS_CHFLAGS(conn
, fname
, new_flags
);
463 DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
464 "file %s! errno=%d\n", new_flags
, fname
, errno
));
468 *attributes_changed
= true;
471 #endif /* HAVE_STAT_DOS_FLAGS */
473 /****************************************************************************
474 Change a unix mode to a dos mode.
475 ****************************************************************************/
477 uint32
dos_mode(connection_struct
*conn
, const char *path
,SMB_STRUCT_STAT
*sbuf
)
480 bool offline
, used_stat_dos_flags
= false;
482 DEBUG(8,("dos_mode: %s\n", path
));
484 if (!VALID_STAT(*sbuf
)) {
488 /* First do any modifications that depend on the path name. */
489 /* hide files with a name starting with a . */
490 if (lp_hide_dot_files(SNUM(conn
))) {
491 const char *p
= strrchr_m(path
,'/');
498 /* Only . and .. are not hidden. */
499 if (p
[0] == '.' && !((p
[1] == '\0') ||
500 (p
[1] == '.' && p
[2] == '\0'))) {
505 #ifdef HAVE_STAT_DOS_FLAGS
506 used_stat_dos_flags
= get_stat_dos_flags(conn
, path
, sbuf
, &result
);
508 if (!used_stat_dos_flags
) {
509 /* Get the DOS attributes from an EA by preference. */
510 if (get_ea_dos_attribute(conn
, path
, sbuf
, &result
)) {
511 result
|= set_sparse_flag(sbuf
);
513 result
|= dos_mode_from_sbuf(conn
, path
, sbuf
);
518 offline
= SMB_VFS_IS_OFFLINE(conn
, path
, sbuf
);
519 if (S_ISREG(sbuf
->st_mode
) && offline
) {
520 result
|= FILE_ATTRIBUTE_OFFLINE
;
523 /* Optimization : Only call is_hidden_path if it's not already
525 if (!(result
& aHIDDEN
) && IS_HIDDEN_PATH(conn
,path
)) {
529 if (Protocol
<= PROTOCOL_LANMAN2
) {
530 DEBUG(10,("dos_mode : filtering result 0x%x\n",
531 (unsigned int)result
));
535 DEBUG(8,("dos_mode returning "));
537 if (result
& aHIDDEN
) DEBUG(8, ("h"));
538 if (result
& aRONLY
) DEBUG(8, ("r"));
539 if (result
& aSYSTEM
) DEBUG(8, ("s"));
540 if (result
& aDIR
) DEBUG(8, ("d"));
541 if (result
& aARCH
) DEBUG(8, ("a"));
542 if (result
& FILE_ATTRIBUTE_SPARSE
) DEBUG(8, ("[sparse]"));
549 /*******************************************************************
550 chmod a file - but preserve some bits.
551 ********************************************************************/
553 int file_set_dosmode(connection_struct
*conn
, const char *fname
,
554 uint32 dosmode
, SMB_STRUCT_STAT
*st
,
555 const char *parent_dir
,
562 int ret
= -1, lret
= -1;
565 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
566 dosmode
&= (SAMBA_ATTRIBUTES_MASK
| FILE_ATTRIBUTE_OFFLINE
);
568 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode
, fname
));
571 SET_STAT_INVALID(st1
);
575 if (!VALID_STAT(*st
)) {
576 if (SMB_VFS_STAT(conn
,fname
,st
))
580 unixmode
= st
->st_mode
;
582 get_acl_group_bits(conn
, fname
, &st
->st_mode
);
584 if (S_ISDIR(st
->st_mode
))
589 old_mode
= dos_mode(conn
,fname
,st
);
591 if (dosmode
& FILE_ATTRIBUTE_OFFLINE
) {
592 if (!(old_mode
& FILE_ATTRIBUTE_OFFLINE
)) {
593 lret
= SMB_VFS_SET_OFFLINE(conn
, fname
);
595 DEBUG(0, ("set_dos_mode: client has asked to set "
596 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
597 "an error while setting it or it is not supported.\n",
603 dosmode
&= ~FILE_ATTRIBUTE_OFFLINE
;
604 old_mode
&= ~FILE_ATTRIBUTE_OFFLINE
;
606 if (old_mode
== dosmode
) {
607 st
->st_mode
= unixmode
;
611 #ifdef HAVE_STAT_DOS_FLAGS
613 bool attributes_changed
;
615 if (set_stat_dos_flags(conn
, fname
, st
, dosmode
,
616 &attributes_changed
))
618 if (!newfile
&& attributes_changed
) {
619 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
620 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
622 st
->st_mode
= unixmode
;
628 /* Store the DOS attributes in an EA by preference. */
629 if (set_ea_dos_attribute(conn
, fname
, st
, dosmode
)) {
631 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
632 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
634 st
->st_mode
= unixmode
;
638 unixmode
= unix_mode(conn
,dosmode
,fname
, parent_dir
);
640 /* preserve the s bits */
641 mask
|= (S_ISUID
| S_ISGID
);
643 /* preserve the t bit */
648 /* possibly preserve the x bits */
649 if (!MAP_ARCHIVE(conn
))
651 if (!MAP_SYSTEM(conn
))
653 if (!MAP_HIDDEN(conn
))
656 unixmode
|= (st
->st_mode
& mask
);
658 /* if we previously had any r bits set then leave them alone */
659 if ((tmp
= st
->st_mode
& (S_IRUSR
|S_IRGRP
|S_IROTH
))) {
660 unixmode
&= ~(S_IRUSR
|S_IRGRP
|S_IROTH
);
664 /* if we previously had any w bits set then leave them alone
665 whilst adding in the new w bits, if the new mode is not rdonly */
666 if (!IS_DOS_READONLY(dosmode
)) {
667 unixmode
|= (st
->st_mode
& (S_IWUSR
|S_IWGRP
|S_IWOTH
));
670 ret
= SMB_VFS_CHMOD(conn
, fname
, unixmode
);
672 if(!newfile
|| (lret
!= -1)) {
673 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
674 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
676 st
->st_mode
= unixmode
;
680 if((errno
!= EPERM
) && (errno
!= EACCES
))
683 if(!lp_dos_filemode(SNUM(conn
)))
686 /* We want DOS semantics, ie allow non owner with write permission to change the
687 bits on a file. Just like file_ntimes below.
690 /* Check if we have write access. */
691 if (CAN_WRITE(conn
)) {
693 * We need to open the file with write access whilst
694 * still in our current user context. This ensures we
695 * are not violating security in doing the fchmod.
696 * This file open does *not* break any oplocks we are
697 * holding. We need to review this.... may need to
698 * break batch oplocks open by others. JRA.
701 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL
, conn
, fname
, st
,
705 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
707 close_file_fchmod(NULL
, fsp
);
709 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
710 FILE_NOTIFY_CHANGE_ATTRIBUTES
, fname
);
713 st
->st_mode
= unixmode
;
720 /*******************************************************************
721 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
723 *******************************************************************/
725 int file_ntimes(connection_struct
*conn
, const char *fname
,
726 struct smb_file_time
*ft
)
728 SMB_STRUCT_STAT sbuf
;
734 DEBUG(6, ("file_ntime: actime: %s",
735 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
736 DEBUG(6, ("file_ntime: modtime: %s",
737 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
738 DEBUG(6, ("file_ntime: createtime: %s",
739 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
741 /* Don't update the time on read-only shares */
742 /* We need this as set_filetime (which can be called on
743 close and other paths) can end up calling this function
744 without the NEED_WRITE protection. Found by :
745 Leo Weppelman <leo@wau.mis.ah.nl>
748 if (!CAN_WRITE(conn
)) {
752 if(SMB_VFS_NTIMES(conn
, fname
, ft
) == 0) {
756 if((errno
!= EPERM
) && (errno
!= EACCES
)) {
760 if(!lp_dos_filetimes(SNUM(conn
))) {
764 /* We have permission (given by the Samba admin) to
765 break POSIX semantics and allow a user to change
766 the time on a file they don't own but can write to
770 /* Check if we have write access. */
771 if (can_write_to_file(conn
, fname
, &sbuf
)) {
772 /* We are allowed to become root and change the filetime. */
774 ret
= SMB_VFS_NTIMES(conn
, fname
, ft
);
781 /******************************************************************
782 Force a "sticky" write time on a pathname. This will always be
783 returned on all future write time queries and set on close.
784 ******************************************************************/
786 bool set_sticky_write_time_path(connection_struct
*conn
, const char *fname
,
787 struct file_id fileid
, const struct timespec mtime
)
789 if (null_timespec(mtime
)) {
793 if (!set_sticky_write_time(fileid
, mtime
)) {
800 /******************************************************************
801 Force a "sticky" write time on an fsp. This will always be
802 returned on all future write time queries and set on close.
803 ******************************************************************/
805 bool set_sticky_write_time_fsp(struct files_struct
*fsp
, const struct timespec mtime
)
807 fsp
->write_time_forced
= true;
808 TALLOC_FREE(fsp
->update_write_time_event
);
810 return set_sticky_write_time_path(fsp
->conn
, fsp
->fsp_name
,
811 fsp
->file_id
, mtime
);
814 /******************************************************************
815 Update a write time immediately, without the 2 second delay.
816 ******************************************************************/
818 bool update_write_time(struct files_struct
*fsp
)
820 if (!set_write_time(fsp
->file_id
, timespec_current())) {
824 notify_fname(fsp
->conn
, NOTIFY_ACTION_MODIFIED
,
825 FILE_NOTIFY_CHANGE_LAST_WRITE
, fsp
->fsp_name
);