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/>.
22 #include "librpc/gen_ndr/ndr_xattr.h"
23 #include "../libcli/security/security.h"
25 static uint32_t filter_mode_by_protocol(uint32_t mode)
27 if (get_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_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf)
41 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
48 /****************************************************************************
49 Change a dos mode to a unix mode.
50 Base permission for files:
51 if creating file and inheriting (i.e. parent_dir != NULL)
52 apply read/write bits from parent directory.
54 everybody gets read bit set
55 dos readonly is represented in unix by removing everyone's write bit
56 dos archive is represented in unix by the user's execute bit
57 dos system is represented in unix by the group's execute bit
58 dos hidden is represented in unix by the other's execute bit
60 Then apply create mask,
63 Base permission for directories:
64 dos directory is represented in unix by unix's dir bit and the exec bit
66 Then apply create mask,
69 ****************************************************************************/
71 mode_t unix_mode(connection_struct *conn, int dosmode,
72 const struct smb_filename *smb_fname,
73 const char *inherit_from_dir)
75 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
76 mode_t dir_mode = 0; /* Mode of the inherit_from directory if
79 if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
80 result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
83 if ((inherit_from_dir != NULL) && lp_inherit_perms(SNUM(conn))) {
84 struct smb_filename *smb_fname_parent = NULL;
87 DEBUG(2, ("unix_mode(%s) inheriting from %s\n",
88 smb_fname_str_dbg(smb_fname),
91 status = create_synthetic_smb_fname(talloc_tos(),
92 inherit_from_dir, NULL,
93 NULL, &smb_fname_parent);
94 if (!NT_STATUS_IS_OK(status)) {
95 DEBUG(1,("unix_mode(%s) failed, [dir %s]: %s\n",
96 smb_fname_str_dbg(smb_fname),
97 inherit_from_dir, nt_errstr(status)));
101 if (SMB_VFS_STAT(conn, smb_fname_parent) != 0) {
102 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",
103 smb_fname_str_dbg(smb_fname),
104 inherit_from_dir, strerror(errno)));
105 TALLOC_FREE(smb_fname_parent);
106 return(0); /* *** shouldn't happen! *** */
109 /* Save for later - but explicitly remove setuid bit for safety. */
110 dir_mode = smb_fname_parent->st.st_ex_mode & ~S_ISUID;
111 DEBUG(2,("unix_mode(%s) inherit mode %o\n",
112 smb_fname_str_dbg(smb_fname), (int)dir_mode));
115 TALLOC_FREE(smb_fname_parent);
118 if (IS_DOS_DIR(dosmode)) {
119 /* We never make directories read only for the owner as under DOS a user
120 can always create a file in a read-only directory. */
121 result |= (S_IFDIR | S_IWUSR);
124 /* Inherit mode of parent directory. */
127 /* Provisionally add all 'x' bits */
128 result |= (S_IXUSR | S_IXGRP | S_IXOTH);
130 /* Apply directory mask */
131 result &= lp_dir_mask(SNUM(conn));
132 /* Add in force bits */
133 result |= lp_force_dir_mode(SNUM(conn));
136 if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
139 if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
142 if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
146 /* Inherit 666 component of parent directory mode */
147 result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
149 /* Apply mode mask */
150 result &= lp_create_mask(SNUM(conn));
151 /* Add in force bits */
152 result |= lp_force_create_mode(SNUM(conn));
156 DEBUG(3,("unix_mode(%s) returning 0%o\n", smb_fname_str_dbg(smb_fname),
161 /****************************************************************************
162 Change a unix mode to a dos mode.
163 ****************************************************************************/
165 static uint32 dos_mode_from_sbuf(connection_struct *conn,
166 const struct smb_filename *smb_fname)
169 enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
171 if (ro_opts == MAP_READONLY_YES) {
172 /* Original Samba method - map inverse of user "w" bit. */
173 if ((smb_fname->st.st_ex_mode & S_IWUSR) == 0) {
176 } else if (ro_opts == MAP_READONLY_PERMISSIONS) {
177 /* Check actual permissions for read-only. */
178 if (!can_write_to_file(conn, smb_fname)) {
181 } /* Else never set the readonly bit. */
183 if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0))
186 if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0))
189 if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0))
192 if (S_ISDIR(smb_fname->st.st_ex_mode))
193 result = aDIR | (result & aRONLY);
195 result |= set_link_read_only_flag(&smb_fname->st);
197 DEBUG(8,("dos_mode_from_sbuf returning "));
199 if (result & aHIDDEN) DEBUG(8, ("h"));
200 if (result & aRONLY ) DEBUG(8, ("r"));
201 if (result & aSYSTEM) DEBUG(8, ("s"));
202 if (result & aDIR ) DEBUG(8, ("d"));
203 if (result & aARCH ) DEBUG(8, ("a"));
209 /****************************************************************************
210 Get DOS attributes from an EA.
211 This can also pull the create time into the stat struct inside smb_fname.
212 ****************************************************************************/
214 static bool get_ea_dos_attribute(connection_struct *conn,
215 struct smb_filename *smb_fname,
218 struct xattr_DOSATTRIB dosattrib;
219 enum ndr_err_code ndr_err;
225 if (!lp_store_dos_attributes(SNUM(conn))) {
229 /* Don't reset pattr to zero as we may already have filename-based attributes we
232 sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name,
233 SAMBA_XATTR_DOS_ATTRIB, attrstr,
238 || errno == ENOTSUP) {
242 DEBUG(1,("get_ea_dos_attribute: Cannot get attribute "
243 "from EA on file %s: Error = %s\n",
244 smb_fname_str_dbg(smb_fname),
246 set_store_dos_attributes(SNUM(conn), False);
251 blob.data = (uint8_t *)attrstr;
252 blob.length = sizeret;
254 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib,
255 (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB);
257 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
258 DEBUG(1,("get_ea_dos_attribute: bad ndr decode "
259 "from EA on file %s: Error = %s\n",
260 smb_fname_str_dbg(smb_fname),
261 ndr_errstr(ndr_err)));
265 DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n",
266 smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex));
268 switch (dosattrib.version) {
270 dosattr = dosattrib.info.compatinfoFFFF.attrib;
273 dosattr = dosattrib.info.info1.attrib;
274 if (!null_nttime(dosattrib.info.info1.create_time)) {
275 struct timespec create_time =
276 nt_time_to_unix_timespec(
277 &dosattrib.info.info1.create_time);
279 update_stat_ex_create_time(&smb_fname->st,
282 DEBUG(10,("get_ea_dos_attribute: file %s case 1 "
284 smb_fname_str_dbg(smb_fname),
285 time_to_asc(convert_timespec_to_time_t(
290 dosattr = dosattrib.info.oldinfo2.attrib;
291 /* Don't know what flags to check for this case. */
294 dosattr = dosattrib.info.info3.attrib;
295 if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
296 !null_nttime(dosattrib.info.info3.create_time)) {
297 struct timespec create_time =
298 nt_time_to_unix_timespec(
299 &dosattrib.info.info3.create_time);
301 update_stat_ex_create_time(&smb_fname->st,
304 DEBUG(10,("get_ea_dos_attribute: file %s case 3 "
306 smb_fname_str_dbg(smb_fname),
307 time_to_asc(convert_timespec_to_time_t(
312 DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on "
313 "file %s - %s\n", smb_fname_str_dbg(smb_fname),
318 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
321 *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
323 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
325 if (dosattr & aHIDDEN) DEBUG(8, ("h"));
326 if (dosattr & aRONLY ) DEBUG(8, ("r"));
327 if (dosattr & aSYSTEM) DEBUG(8, ("s"));
328 if (dosattr & aDIR ) DEBUG(8, ("d"));
329 if (dosattr & aARCH ) DEBUG(8, ("a"));
336 /****************************************************************************
337 Set DOS attributes in an EA.
338 Also sets the create time.
339 ****************************************************************************/
341 static bool set_ea_dos_attribute(connection_struct *conn,
342 struct smb_filename *smb_fname,
345 struct xattr_DOSATTRIB dosattrib;
346 enum ndr_err_code ndr_err;
348 files_struct *fsp = NULL;
351 if (!lp_store_dos_attributes(SNUM(conn))) {
355 ZERO_STRUCT(dosattrib);
358 dosattrib.version = 3;
359 dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB|
360 XATTR_DOSINFO_CREATE_TIME;
361 dosattrib.info.info3.attrib = dosmode;
362 unix_timespec_to_nt_time(&dosattrib.info.info3.create_time,
363 smb_fname->st.st_ex_btime);
365 DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n",
366 (unsigned int)dosmode,
367 time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)),
368 smb_fname_str_dbg(smb_fname) ));
370 ndr_err = ndr_push_struct_blob(
371 &blob, talloc_tos(), &dosattrib,
372 (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB);
374 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
375 DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n",
376 ndr_errstr(ndr_err)));
380 if (blob.data == NULL || blob.length == 0) {
384 if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
385 SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length,
387 if((errno != EPERM) && (errno != EACCES)) {
390 || errno == ENOTSUP) {
394 DEBUG(1,("set_ea_dos_attributes: Cannot set "
395 "attribute EA on file %s: Error = %s\n",
396 smb_fname_str_dbg(smb_fname),
398 set_store_dos_attributes(SNUM(conn), False);
403 /* We want DOS semantics, ie allow non owner with write permission to change the
404 bits on a file. Just like file_ntimes below.
407 /* Check if we have write access. */
408 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
412 * We need to open the file with write access whilst
413 * still in our current user context. This ensures we
414 * are not violating security in doing the setxattr.
417 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname,
421 if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
422 SAMBA_XATTR_DOS_ATTRIB, blob.data,
423 blob.length, 0) == 0) {
427 close_file_fchmod(NULL, fsp);
430 DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n",
431 (unsigned int)dosmode,
432 smb_fname_str_dbg(smb_fname)));
436 /****************************************************************************
437 Change a unix mode to a dos mode for an ms dfs link.
438 ****************************************************************************/
440 uint32 dos_mode_msdfs(connection_struct *conn,
441 const struct smb_filename *smb_fname)
445 DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname)));
447 if (!VALID_STAT(smb_fname->st)) {
451 /* First do any modifications that depend on the path name. */
452 /* hide files with a name starting with a . */
453 if (lp_hide_dot_files(SNUM(conn))) {
454 const char *p = strrchr_m(smb_fname->base_name, '/');
458 p = smb_fname->base_name;
461 /* Only . and .. are not hidden. */
462 if (p[0] == '.' && !((p[1] == '\0') ||
463 (p[1] == '.' && p[2] == '\0'))) {
468 result |= dos_mode_from_sbuf(conn, smb_fname);
470 /* Optimization : Only call is_hidden_path if it's not already
472 if (!(result & aHIDDEN) &&
473 IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
478 result = FILE_ATTRIBUTE_NORMAL;
481 result = filter_mode_by_protocol(result);
483 DEBUG(8,("dos_mode_msdfs returning "));
485 if (result & aHIDDEN) DEBUG(8, ("h"));
486 if (result & aRONLY ) DEBUG(8, ("r"));
487 if (result & aSYSTEM) DEBUG(8, ("s"));
488 if (result & aDIR ) DEBUG(8, ("d"));
489 if (result & aARCH ) DEBUG(8, ("a"));
490 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
497 #ifdef HAVE_STAT_DOS_FLAGS
498 /****************************************************************************
499 Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*)
500 ****************************************************************************/
502 int dos_attributes_to_stat_dos_flags(uint32_t dosmode)
504 uint32_t dos_stat_flags = 0;
507 dos_stat_flags |= UF_DOS_ARCHIVE;
508 if (dosmode & aHIDDEN)
509 dos_stat_flags |= UF_DOS_HIDDEN;
510 if (dosmode & aRONLY)
511 dos_stat_flags |= UF_DOS_RO;
512 if (dosmode & aSYSTEM)
513 dos_stat_flags |= UF_DOS_SYSTEM;
514 if (dosmode & FILE_ATTRIBUTE_NONINDEXED)
515 dos_stat_flags |= UF_DOS_NOINDEX;
517 return dos_stat_flags;
520 /****************************************************************************
521 Gets DOS attributes, accessed via st_ex_flags in the stat struct.
522 ****************************************************************************/
524 static bool get_stat_dos_flags(connection_struct *conn,
525 const struct smb_filename *smb_fname,
528 SMB_ASSERT(VALID_STAT(smb_fname->st));
531 if (!lp_store_dos_attributes(SNUM(conn))) {
535 DEBUG(5, ("Getting stat dos attributes for %s.\n",
536 smb_fname_str_dbg(smb_fname)));
538 if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE)
540 if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN)
542 if (smb_fname->st.st_ex_flags & UF_DOS_RO)
544 if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM)
546 if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX)
547 *dosmode |= FILE_ATTRIBUTE_NONINDEXED;
548 if (smb_fname->st.st_ex_flags & FILE_ATTRIBUTE_SPARSE)
549 *dosmode |= FILE_ATTRIBUTE_SPARSE;
550 if (S_ISDIR(smb_fname->st.st_ex_mode))
553 *dosmode |= set_link_read_only_flag(&smb_fname->st);
558 /****************************************************************************
559 Sets DOS attributes, stored in st_ex_flags of the inode.
560 ****************************************************************************/
562 static bool set_stat_dos_flags(connection_struct *conn,
563 const struct smb_filename *smb_fname,
565 bool *attributes_changed)
567 uint32_t new_flags = 0;
570 SMB_ASSERT(VALID_STAT(smb_fname->st));
571 SMB_ASSERT(attributes_changed);
573 *attributes_changed = false;
575 if (!lp_store_dos_attributes(SNUM(conn))) {
579 DEBUG(5, ("Setting stat dos attributes for %s.\n",
580 smb_fname_str_dbg(smb_fname)));
582 new_flags = (smb_fname->st.st_ex_flags & ~UF_DOS_FLAGS) |
583 dos_attributes_to_stat_dos_flags(dosmode);
585 /* Return early if no flags changed. */
586 if (new_flags == smb_fname->st.st_ex_flags)
589 DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
590 smb_fname->st.st_ex_flags));
592 /* Set new flags with chflags. */
593 error = SMB_VFS_CHFLAGS(conn, smb_fname->base_name, new_flags);
595 DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
596 "file %s! errno=%d\n", new_flags,
597 smb_fname_str_dbg(smb_fname), errno));
601 *attributes_changed = true;
604 #endif /* HAVE_STAT_DOS_FLAGS */
606 /****************************************************************************
607 Change a unix mode to a dos mode.
608 May also read the create timespec into the stat struct in smb_fname
609 if "store dos attributes" is true.
610 ****************************************************************************/
612 uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
615 bool offline, used_stat_dos_flags = false;
617 DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname)));
619 if (!VALID_STAT(smb_fname->st)) {
623 /* First do any modifications that depend on the path name. */
624 /* hide files with a name starting with a . */
625 if (lp_hide_dot_files(SNUM(conn))) {
626 const char *p = strrchr_m(smb_fname->base_name,'/');
630 p = smb_fname->base_name;
633 /* Only . and .. are not hidden. */
634 if (p[0] == '.' && !((p[1] == '\0') ||
635 (p[1] == '.' && p[2] == '\0'))) {
640 #ifdef HAVE_STAT_DOS_FLAGS
641 used_stat_dos_flags = get_stat_dos_flags(conn, smb_fname, &result);
643 if (!used_stat_dos_flags) {
644 /* Get the DOS attributes from an EA by preference. */
645 if (!get_ea_dos_attribute(conn, smb_fname, &result)) {
646 result |= dos_mode_from_sbuf(conn, smb_fname);
650 offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &smb_fname->st);
651 if (S_ISREG(smb_fname->st.st_ex_mode) && offline) {
652 result |= FILE_ATTRIBUTE_OFFLINE;
655 /* Optimization : Only call is_hidden_path if it's not already
657 if (!(result & aHIDDEN) &&
658 IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
663 result = FILE_ATTRIBUTE_NORMAL;
666 result = filter_mode_by_protocol(result);
668 DEBUG(8,("dos_mode returning "));
670 if (result & aHIDDEN) DEBUG(8, ("h"));
671 if (result & aRONLY ) DEBUG(8, ("r"));
672 if (result & aSYSTEM) DEBUG(8, ("s"));
673 if (result & aDIR ) DEBUG(8, ("d"));
674 if (result & aARCH ) DEBUG(8, ("a"));
675 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
682 /*******************************************************************
683 chmod a file - but preserve some bits.
684 If "store dos attributes" is also set it will store the create time
685 from the stat struct in smb_fname (in NTTIME format) in the EA
687 ********************************************************************/
689 int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
690 uint32 dosmode, const char *parent_dir, bool newfile)
695 int ret = -1, lret = -1;
697 struct timespec new_create_timespec;
699 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
700 dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
702 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n",
703 dosmode, smb_fname_str_dbg(smb_fname)));
705 unixmode = smb_fname->st.st_ex_mode;
707 get_acl_group_bits(conn, smb_fname->base_name,
708 &smb_fname->st.st_ex_mode);
710 if (S_ISDIR(smb_fname->st.st_ex_mode))
715 new_create_timespec = smb_fname->st.st_ex_btime;
717 old_mode = dos_mode(conn, smb_fname);
719 if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
720 if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
721 lret = SMB_VFS_SET_OFFLINE(conn, smb_fname->base_name);
723 DEBUG(0, ("set_dos_mode: client has asked to "
724 "set FILE_ATTRIBUTE_OFFLINE to "
725 "%s/%s but there was an error while "
726 "setting it or it is not "
727 "supported.\n", parent_dir,
728 smb_fname_str_dbg(smb_fname)));
733 dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
734 old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
736 smb_fname->st.st_ex_btime = new_create_timespec;
738 #ifdef HAVE_STAT_DOS_FLAGS
740 bool attributes_changed;
742 if (set_stat_dos_flags(conn, smb_fname, dosmode,
743 &attributes_changed))
745 if (!newfile && attributes_changed) {
746 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
747 FILE_NOTIFY_CHANGE_ATTRIBUTES,
748 smb_fname->base_name);
750 smb_fname->st.st_ex_mode = unixmode;
755 /* Store the DOS attributes in an EA by preference. */
756 if (set_ea_dos_attribute(conn, smb_fname, dosmode)) {
758 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
759 FILE_NOTIFY_CHANGE_ATTRIBUTES,
760 smb_fname->base_name);
762 smb_fname->st.st_ex_mode = unixmode;
766 unixmode = unix_mode(conn, dosmode, smb_fname, parent_dir);
768 /* preserve the s bits */
769 mask |= (S_ISUID | S_ISGID);
771 /* preserve the t bit */
776 /* possibly preserve the x bits */
777 if (!MAP_ARCHIVE(conn))
779 if (!MAP_SYSTEM(conn))
781 if (!MAP_HIDDEN(conn))
784 unixmode |= (smb_fname->st.st_ex_mode & mask);
786 /* if we previously had any r bits set then leave them alone */
787 if ((tmp = smb_fname->st.st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
788 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
792 /* if we previously had any w bits set then leave them alone
793 whilst adding in the new w bits, if the new mode is not rdonly */
794 if (!IS_DOS_READONLY(dosmode)) {
795 unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
798 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
800 if(!newfile || (lret != -1)) {
801 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
802 FILE_NOTIFY_CHANGE_ATTRIBUTES,
803 smb_fname->base_name);
805 smb_fname->st.st_ex_mode = unixmode;
809 if((errno != EPERM) && (errno != EACCES))
812 if(!lp_dos_filemode(SNUM(conn)))
815 /* We want DOS semantics, ie allow non owner with write permission to change the
816 bits on a file. Just like file_ntimes below.
819 /* Check if we have write access. */
820 if (CAN_WRITE(conn)) {
822 * We need to open the file with write access whilst
823 * still in our current user context. This ensures we
824 * are not violating security in doing the fchmod.
825 * This file open does *not* break any oplocks we are
826 * holding. We need to review this.... may need to
827 * break batch oplocks open by others. JRA.
830 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname,
834 ret = SMB_VFS_FCHMOD(fsp, unixmode);
836 close_file_fchmod(NULL, fsp);
838 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
839 FILE_NOTIFY_CHANGE_ATTRIBUTES,
840 smb_fname->base_name);
843 smb_fname->st.st_ex_mode = unixmode;
851 NTSTATUS file_set_sparse(connection_struct *conn,
855 uint32_t old_dosmode;
856 uint32_t new_dosmode;
859 if (!CAN_WRITE(conn)) {
860 DEBUG(9,("file_set_sparse: fname[%s] set[%u] "
861 "on readonly share[%s]\n",
862 smb_fname_str_dbg(fsp->fsp_name),
864 lp_servicename(SNUM(conn))));
865 return NT_STATUS_MEDIA_WRITE_PROTECTED;
868 if (!(fsp->access_mask & FILE_WRITE_DATA) &&
869 !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
870 DEBUG(9,("file_set_sparse: fname[%s] set[%u] "
871 "access_mask[0x%08X] - access denied\n",
872 smb_fname_str_dbg(fsp->fsp_name),
875 return NT_STATUS_ACCESS_DENIED;
878 DEBUG(10,("file_set_sparse: setting sparse bit %u on file %s\n",
879 sparse, smb_fname_str_dbg(fsp->fsp_name)));
881 if (!lp_store_dos_attributes(SNUM(conn))) {
882 return NT_STATUS_INVALID_DEVICE_REQUEST;
885 status = vfs_stat_fsp(fsp);
886 if (!NT_STATUS_IS_OK(status)) {
890 old_dosmode = dos_mode(conn, fsp->fsp_name);
892 if (sparse && !(old_dosmode & FILE_ATTRIBUTE_SPARSE)) {
893 new_dosmode = old_dosmode | FILE_ATTRIBUTE_SPARSE;
894 } else if (!sparse && (old_dosmode & FILE_ATTRIBUTE_SPARSE)) {
895 new_dosmode = old_dosmode & ~FILE_ATTRIBUTE_SPARSE;
900 /* Store the DOS attributes in an EA. */
901 if (!set_ea_dos_attribute(conn, fsp->fsp_name,
906 return map_nt_error_from_unix(errno);
909 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
910 FILE_NOTIFY_CHANGE_ATTRIBUTES,
911 fsp->fsp_name->base_name);
916 /*******************************************************************
917 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
919 *******************************************************************/
921 int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
922 struct smb_file_time *ft)
928 DEBUG(6, ("file_ntime: actime: %s",
929 time_to_asc(convert_timespec_to_time_t(ft->atime))));
930 DEBUG(6, ("file_ntime: modtime: %s",
931 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
932 DEBUG(6, ("file_ntime: ctime: %s",
933 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
934 DEBUG(6, ("file_ntime: createtime: %s",
935 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
937 /* Don't update the time on read-only shares */
938 /* We need this as set_filetime (which can be called on
939 close and other paths) can end up calling this function
940 without the NEED_WRITE protection. Found by :
941 Leo Weppelman <leo@wau.mis.ah.nl>
944 if (!CAN_WRITE(conn)) {
948 if(SMB_VFS_NTIMES(conn, smb_fname, ft) == 0) {
952 if((errno != EPERM) && (errno != EACCES)) {
956 if(!lp_dos_filetimes(SNUM(conn))) {
960 /* We have permission (given by the Samba admin) to
961 break POSIX semantics and allow a user to change
962 the time on a file they don't own but can write to
966 /* Check if we have write access. */
967 if (can_write_to_file(conn, smb_fname)) {
968 /* We are allowed to become root and change the filetime. */
970 ret = SMB_VFS_NTIMES(conn, smb_fname, ft);
977 /******************************************************************
978 Force a "sticky" write time on a pathname. This will always be
979 returned on all future write time queries and set on close.
980 ******************************************************************/
982 bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime)
984 if (null_timespec(mtime)) {
988 if (!set_sticky_write_time(fileid, mtime)) {
995 /******************************************************************
996 Force a "sticky" write time on an fsp. This will always be
997 returned on all future write time queries and set on close.
998 ******************************************************************/
1000 bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
1002 if (null_timespec(mtime)) {
1006 fsp->write_time_forced = true;
1007 TALLOC_FREE(fsp->update_write_time_event);
1009 return set_sticky_write_time_path(fsp->file_id, mtime);
1012 /******************************************************************
1013 Set a create time EA.
1014 ******************************************************************/
1016 NTSTATUS set_create_timespec_ea(connection_struct *conn,
1017 const struct smb_filename *psmb_fname,
1018 struct timespec create_time)
1021 struct smb_filename *smb_fname = NULL;
1025 if (!lp_store_dos_attributes(SNUM(conn))) {
1026 return NT_STATUS_OK;
1029 status = create_synthetic_smb_fname(talloc_tos(),
1030 psmb_fname->base_name,
1031 NULL, &psmb_fname->st,
1034 if (!NT_STATUS_IS_OK(status)) {
1038 dosmode = dos_mode(conn, smb_fname);
1040 smb_fname->st.st_ex_btime = create_time;
1042 ret = file_set_dosmode(conn, smb_fname, dosmode, NULL, false);
1044 map_nt_error_from_unix(errno);
1047 DEBUG(10,("set_create_timespec_ea: wrote create time EA for file %s\n",
1048 smb_fname_str_dbg(smb_fname)));
1050 return NT_STATUS_OK;
1053 /******************************************************************
1054 Return a create time.
1055 ******************************************************************/
1057 struct timespec get_create_timespec(connection_struct *conn,
1058 struct files_struct *fsp,
1059 const struct smb_filename *smb_fname)
1061 return smb_fname->st.st_ex_btime;
1064 /******************************************************************
1065 Return a change time (may look at EA in future).
1066 ******************************************************************/
1068 struct timespec get_change_timespec(connection_struct *conn,
1069 struct files_struct *fsp,
1070 const struct smb_filename *smb_fname)
1072 return smb_fname->st.st_ex_mtime;