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 (vfs_stat_smb_fname(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, const 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 struct smb_filename *smb_fname = NULL;
157 status = create_synthetic_smb_fname_split(talloc_tos(), path,
159 if (NT_STATUS_IS_OK(status)) {
160 /* Check actual permissions for read-only. */
161 if (!can_write_to_file(conn, smb_fname)) {
165 TALLOC_FREE(smb_fname);
166 } /* Else never set the readonly bit. */
168 if (MAP_ARCHIVE(conn) && ((sbuf->st_ex_mode & S_IXUSR) != 0))
171 if (MAP_SYSTEM(conn) && ((sbuf->st_ex_mode & S_IXGRP) != 0))
174 if (MAP_HIDDEN(conn) && ((sbuf->st_ex_mode & S_IXOTH) != 0))
177 if (S_ISDIR(sbuf->st_ex_mode))
178 result = aDIR | (result & aRONLY);
180 result |= set_sparse_flag(sbuf);
181 result |= set_link_read_only_flag(sbuf);
183 DEBUG(8,("dos_mode_from_sbuf returning "));
185 if (result & aHIDDEN) DEBUG(8, ("h"));
186 if (result & aRONLY ) DEBUG(8, ("r"));
187 if (result & aSYSTEM) DEBUG(8, ("s"));
188 if (result & aDIR ) DEBUG(8, ("d"));
189 if (result & aARCH ) DEBUG(8, ("a"));
195 /****************************************************************************
196 Get DOS attributes from an EA.
197 ****************************************************************************/
199 static bool get_ea_dos_attribute(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf, uint32 *pattr)
203 unsigned int dosattr;
205 if (!lp_store_dos_attributes(SNUM(conn))) {
209 /* Don't reset pattr to zero as we may already have filename-based attributes we
212 sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
216 || errno == ENOTSUP) {
220 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
221 path, strerror(errno) ));
222 set_store_dos_attributes(SNUM(conn), False);
226 /* Null terminate string. */
227 attrstr[sizeret] = 0;
228 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
230 if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
231 sscanf(attrstr, "%x", &dosattr) != 1) {
232 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
236 if (S_ISDIR(sbuf->st_ex_mode)) {
239 *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
241 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
243 if (dosattr & aHIDDEN) DEBUG(8, ("h"));
244 if (dosattr & aRONLY ) DEBUG(8, ("r"));
245 if (dosattr & aSYSTEM) DEBUG(8, ("s"));
246 if (dosattr & aDIR ) DEBUG(8, ("d"));
247 if (dosattr & aARCH ) DEBUG(8, ("a"));
254 /****************************************************************************
255 Set DOS attributes in an EA.
256 ****************************************************************************/
258 static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
261 files_struct *fsp = NULL;
264 if (!lp_store_dos_attributes(SNUM(conn))) {
268 snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
269 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
270 if((errno != EPERM) && (errno != EACCES)) {
273 || errno == ENOTSUP) {
277 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
278 path, strerror(errno) ));
279 set_store_dos_attributes(SNUM(conn), False);
284 /* We want DOS semantics, ie allow non owner with write permission to change the
285 bits on a file. Just like file_ntimes below.
288 /* Check if we have write access. */
289 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
293 * We need to open the file with write access whilst
294 * still in our current user context. This ensures we
295 * are not violating security in doing the setxattr.
298 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, path, sbuf,
302 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
306 close_file_fchmod(NULL, fsp);
309 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
313 /****************************************************************************
314 Change a unix mode to a dos mode for an ms dfs link.
315 ****************************************************************************/
317 uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *psbuf)
319 SMB_STRUCT_STAT sbuf = *psbuf;
322 DEBUG(8,("dos_mode_msdfs: %s\n", path));
324 if (!VALID_STAT(sbuf)) {
328 /* First do any modifications that depend on the path name. */
329 /* hide files with a name starting with a . */
330 if (lp_hide_dot_files(SNUM(conn))) {
331 const char *p = strrchr_m(path,'/');
338 /* Only . and .. are not hidden. */
339 if (p[0] == '.' && !((p[1] == '\0') ||
340 (p[1] == '.' && p[2] == '\0'))) {
345 result |= dos_mode_from_sbuf(conn, path, &sbuf);
347 /* Optimization : Only call is_hidden_path if it's not already
349 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
353 DEBUG(8,("dos_mode_msdfs returning "));
355 if (result & aHIDDEN) DEBUG(8, ("h"));
356 if (result & aRONLY ) DEBUG(8, ("r"));
357 if (result & aSYSTEM) DEBUG(8, ("s"));
358 if (result & aDIR ) DEBUG(8, ("d"));
359 if (result & aARCH ) DEBUG(8, ("a"));
360 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
367 #ifdef HAVE_STAT_DOS_FLAGS
368 /****************************************************************************
369 Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*)
370 ****************************************************************************/
372 int dos_attributes_to_stat_dos_flags(uint32_t dosmode)
374 uint32_t dos_stat_flags = 0;
377 dos_stat_flags |= UF_DOS_ARCHIVE;
378 if (dosmode & aHIDDEN)
379 dos_stat_flags |= UF_DOS_HIDDEN;
380 if (dosmode & aRONLY)
381 dos_stat_flags |= UF_DOS_RO;
382 if (dosmode & aSYSTEM)
383 dos_stat_flags |= UF_DOS_SYSTEM;
384 if (dosmode & FILE_ATTRIBUTE_NONINDEXED)
385 dos_stat_flags |= UF_DOS_NOINDEX;
387 return dos_stat_flags;
390 /****************************************************************************
391 Gets DOS attributes, accessed via st_ex_flags in the stat struct.
392 ****************************************************************************/
394 static bool get_stat_dos_flags(connection_struct *conn,
396 const SMB_STRUCT_STAT *sbuf,
399 SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
402 if (!lp_store_dos_attributes(SNUM(conn))) {
406 DEBUG(5, ("Getting stat dos attributes for %s.\n", fname));
408 if (sbuf->st_ex_flags & UF_DOS_ARCHIVE)
410 if (sbuf->st_ex_flags & UF_DOS_HIDDEN)
412 if (sbuf->st_ex_flags & UF_DOS_RO)
414 if (sbuf->st_ex_flags & UF_DOS_SYSTEM)
416 if (sbuf->st_ex_flags & UF_DOS_NOINDEX)
417 *dosmode |= FILE_ATTRIBUTE_NONINDEXED;
418 if (S_ISDIR(sbuf->st_ex_mode))
421 *dosmode |= set_sparse_flag(sbuf);
422 *dosmode |= set_link_read_only_flag(sbuf);
427 /****************************************************************************
428 Sets DOS attributes, stored in st_ex_flags of the inode.
429 ****************************************************************************/
431 static bool set_stat_dos_flags(connection_struct *conn,
433 SMB_STRUCT_STAT *sbuf,
435 bool *attributes_changed)
437 uint32_t new_flags = 0;
440 SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
441 SMB_ASSERT(attributes_changed);
443 *attributes_changed = false;
445 if (!lp_store_dos_attributes(SNUM(conn))) {
449 DEBUG(5, ("Setting stat dos attributes for %s.\n", fname));
451 new_flags = (sbuf->st_ex_flags & ~UF_DOS_FLAGS) |
452 dos_attributes_to_stat_dos_flags(dosmode);
454 /* Return early if no flags changed. */
455 if (new_flags == sbuf->st_ex_flags)
458 DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
461 /* Set new flags with chflags. */
462 error = SMB_VFS_CHFLAGS(conn, fname, new_flags);
464 DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
465 "file %s! errno=%d\n", new_flags, fname, errno));
469 *attributes_changed = true;
472 #endif /* HAVE_STAT_DOS_FLAGS */
474 /****************************************************************************
475 Change a unix mode to a dos mode.
476 ****************************************************************************/
478 uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *psbuf)
480 SMB_STRUCT_STAT sbuf = *psbuf;
482 bool offline, used_stat_dos_flags = false;
484 DEBUG(8,("dos_mode: %s\n", path));
486 if (!VALID_STAT(sbuf)) {
490 /* First do any modifications that depend on the path name. */
491 /* hide files with a name starting with a . */
492 if (lp_hide_dot_files(SNUM(conn))) {
493 const char *p = strrchr_m(path,'/');
500 /* Only . and .. are not hidden. */
501 if (p[0] == '.' && !((p[1] == '\0') ||
502 (p[1] == '.' && p[2] == '\0'))) {
507 #ifdef HAVE_STAT_DOS_FLAGS
508 used_stat_dos_flags = get_stat_dos_flags(conn, path, &sbuf, &result);
510 if (!used_stat_dos_flags) {
511 /* Get the DOS attributes from an EA by preference. */
512 if (get_ea_dos_attribute(conn, path, &sbuf, &result)) {
513 result |= set_sparse_flag(&sbuf);
515 result |= dos_mode_from_sbuf(conn, path, &sbuf);
519 offline = SMB_VFS_IS_OFFLINE(conn, path, &sbuf);
520 if (S_ISREG(sbuf.st_ex_mode) && offline) {
521 result |= FILE_ATTRIBUTE_OFFLINE;
524 /* Optimization : Only call is_hidden_path if it's not already
526 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
530 DEBUG(8,("dos_mode returning "));
532 if (result & aHIDDEN) DEBUG(8, ("h"));
533 if (result & aRONLY ) DEBUG(8, ("r"));
534 if (result & aSYSTEM) DEBUG(8, ("s"));
535 if (result & aDIR ) DEBUG(8, ("d"));
536 if (result & aARCH ) DEBUG(8, ("a"));
537 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
544 /*******************************************************************
545 chmod a file - but preserve some bits.
546 ********************************************************************/
548 int file_set_dosmode(connection_struct *conn, const char *fname,
549 uint32 dosmode, SMB_STRUCT_STAT *st,
550 const char *parent_dir,
557 int ret = -1, lret = -1;
560 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
561 dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
563 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
566 SET_STAT_INVALID(st1);
570 if (!VALID_STAT(*st)) {
571 if (vfs_stat_smb_fname(conn,fname,st))
575 unixmode = st->st_ex_mode;
577 get_acl_group_bits(conn, fname, &st->st_ex_mode);
579 if (S_ISDIR(st->st_ex_mode))
584 old_mode = dos_mode(conn,fname,st);
586 if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
587 if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
588 lret = SMB_VFS_SET_OFFLINE(conn, fname);
590 DEBUG(0, ("set_dos_mode: client has asked to set "
591 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
592 "an error while setting it or it is not supported.\n",
598 dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
599 old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
601 if (old_mode == dosmode) {
602 st->st_ex_mode = unixmode;
606 #ifdef HAVE_STAT_DOS_FLAGS
608 bool attributes_changed;
610 if (set_stat_dos_flags(conn, fname, st, dosmode,
611 &attributes_changed))
613 if (!newfile && attributes_changed) {
614 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
615 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
617 st->st_ex_mode = unixmode;
623 /* Store the DOS attributes in an EA by preference. */
624 if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
626 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
627 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
629 st->st_ex_mode = unixmode;
633 unixmode = unix_mode(conn,dosmode,fname, parent_dir);
635 /* preserve the s bits */
636 mask |= (S_ISUID | S_ISGID);
638 /* preserve the t bit */
643 /* possibly preserve the x bits */
644 if (!MAP_ARCHIVE(conn))
646 if (!MAP_SYSTEM(conn))
648 if (!MAP_HIDDEN(conn))
651 unixmode |= (st->st_ex_mode & mask);
653 /* if we previously had any r bits set then leave them alone */
654 if ((tmp = st->st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
655 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
659 /* if we previously had any w bits set then leave them alone
660 whilst adding in the new w bits, if the new mode is not rdonly */
661 if (!IS_DOS_READONLY(dosmode)) {
662 unixmode |= (st->st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
665 ret = SMB_VFS_CHMOD(conn, fname, unixmode);
667 if(!newfile || (lret != -1)) {
668 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
669 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
671 st->st_ex_mode = unixmode;
675 if((errno != EPERM) && (errno != EACCES))
678 if(!lp_dos_filemode(SNUM(conn)))
681 /* We want DOS semantics, ie allow non owner with write permission to change the
682 bits on a file. Just like file_ntimes below.
685 /* Check if we have write access. */
686 if (CAN_WRITE(conn)) {
688 * We need to open the file with write access whilst
689 * still in our current user context. This ensures we
690 * are not violating security in doing the fchmod.
691 * This file open does *not* break any oplocks we are
692 * holding. We need to review this.... may need to
693 * break batch oplocks open by others. JRA.
696 if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, st,
700 ret = SMB_VFS_FCHMOD(fsp, unixmode);
702 close_file_fchmod(NULL, fsp);
704 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
705 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
708 st->st_ex_mode = unixmode;
715 /*******************************************************************
716 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
718 *******************************************************************/
720 int file_ntimes(connection_struct *conn, const char *fname,
721 struct smb_file_time *ft)
723 struct smb_filename *smb_fname = NULL;
729 DEBUG(6, ("file_ntime: actime: %s",
730 time_to_asc(convert_timespec_to_time_t(ft->atime))));
731 DEBUG(6, ("file_ntime: modtime: %s",
732 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
733 DEBUG(6, ("file_ntime: createtime: %s",
734 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
736 /* Don't update the time on read-only shares */
737 /* We need this as set_filetime (which can be called on
738 close and other paths) can end up calling this function
739 without the NEED_WRITE protection. Found by :
740 Leo Weppelman <leo@wau.mis.ah.nl>
743 if (!CAN_WRITE(conn)) {
747 if(SMB_VFS_NTIMES(conn, fname, ft) == 0) {
751 if((errno != EPERM) && (errno != EACCES)) {
755 if(!lp_dos_filetimes(SNUM(conn))) {
759 /* We have permission (given by the Samba admin) to
760 break POSIX semantics and allow a user to change
761 the time on a file they don't own but can write to
765 status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
768 if (!NT_STATUS_IS_OK(status)) {
772 /* Check if we have write access. */
773 if (can_write_to_file(conn, smb_fname)) {
774 /* We are allowed to become root and change the filetime. */
776 ret = SMB_VFS_NTIMES(conn, fname, ft);
779 TALLOC_FREE(smb_fname);
784 /******************************************************************
785 Force a "sticky" write time on a pathname. This will always be
786 returned on all future write time queries and set on close.
787 ******************************************************************/
789 bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
790 struct file_id fileid, const struct timespec mtime)
792 if (null_timespec(mtime)) {
796 if (!set_sticky_write_time(fileid, mtime)) {
803 /******************************************************************
804 Force a "sticky" write time on an fsp. This will always be
805 returned on all future write time queries and set on close.
806 ******************************************************************/
808 bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
810 fsp->write_time_forced = true;
811 TALLOC_FREE(fsp->update_write_time_event);
813 return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
814 fsp->file_id, mtime);
817 /******************************************************************
818 Update a write time immediately, without the 2 second delay.
819 ******************************************************************/
821 bool update_write_time(struct files_struct *fsp)
823 if (!set_write_time(fsp->file_id, timespec_current())) {
827 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
828 FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);