source: branches/samba-3.2.x/source/smbd/dosmode.c

Last change on this file was 243, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #41 in 3.2 branch

File size: 19.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 dos mode handling functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) James Peach 2006
6
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.
11
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.
16
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/>.
19*/
20
21#include "includes.h"
22
23static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
24{
25#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
26 if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
27 return FILE_ATTRIBUTE_SPARSE;
28 }
29#endif
30 return 0;
31}
32
33/****************************************************************************
34 Change a dos mode to a unix mode.
35 Base permission for files:
36 if creating file and inheriting (i.e. parent_dir != NULL)
37 apply read/write bits from parent directory.
38 else
39 everybody gets read bit set
40 dos readonly is represented in unix by removing everyone's write bit
41 dos archive is represented in unix by the user's execute bit
42 dos system is represented in unix by the group's execute bit
43 dos hidden is represented in unix by the other's execute bit
44 if !inheriting {
45 Then apply create mask,
46 then add force bits.
47 }
48 Base permission for directories:
49 dos directory is represented in unix by unix's dir bit and the exec bit
50 if !inheriting {
51 Then apply create mask,
52 then add force bits.
53 }
54****************************************************************************/
55
56mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
57 const char *inherit_from_dir)
58{
59 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
60 mode_t dir_mode = 0; /* Mode of the inherit_from directory if
61 * inheriting. */
62
63 if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
64 result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
65 }
66
67 if (fname && (inherit_from_dir != NULL)
68 && lp_inherit_perms(SNUM(conn))) {
69 SMB_STRUCT_STAT sbuf;
70
71 DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
72 inherit_from_dir));
73 if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
74 DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
75 inherit_from_dir, strerror(errno)));
76 return(0); /* *** shouldn't happen! *** */
77 }
78
79 /* Save for later - but explicitly remove setuid bit for safety. */
80 dir_mode = sbuf.st_mode & ~S_ISUID;
81 DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
82 /* Clear "result" */
83 result = 0;
84 }
85
86 if (IS_DOS_DIR(dosmode)) {
87 /* We never make directories read only for the owner as under DOS a user
88 can always create a file in a read-only directory. */
89 result |= (S_IFDIR | S_IWUSR);
90
91 if (dir_mode) {
92 /* Inherit mode of parent directory. */
93 result |= dir_mode;
94 } else {
95 /* Provisionally add all 'x' bits */
96 result |= (S_IXUSR | S_IXGRP | S_IXOTH);
97
98 /* Apply directory mask */
99 result &= lp_dir_mask(SNUM(conn));
100 /* Add in force bits */
101 result |= lp_force_dir_mode(SNUM(conn));
102 }
103 } else {
104 if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
105 result |= S_IXUSR;
106
107 if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
108 result |= S_IXGRP;
109
110 if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
111 result |= S_IXOTH;
112
113 if (dir_mode) {
114 /* Inherit 666 component of parent directory mode */
115 result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
116 } else {
117 /* Apply mode mask */
118 result &= lp_create_mask(SNUM(conn));
119 /* Add in force bits */
120 result |= lp_force_create_mode(SNUM(conn));
121 }
122 }
123
124 DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
125 return(result);
126}
127
128/****************************************************************************
129 Change a unix mode to a dos mode.
130****************************************************************************/
131
132static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
133{
134 int result = 0;
135 enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
136
137 if (ro_opts == MAP_READONLY_YES) {
138 /* Original Samba method - map inverse of user "w" bit. */
139#ifndef __OS2__x
140 if ((sbuf->st_mode & S_IWUSR) == 0) {
141#else
142 if(os2_isattribute(path,aRONLY)==0) {
143#endif
144 result |= aRONLY;
145 }
146 } else if (ro_opts == MAP_READONLY_PERMISSIONS) {
147 /* Check actual permissions for read-only. */
148 if (!can_write_to_file(conn, path, sbuf)) {
149 result |= aRONLY;
150 }
151 } /* Else never set the readonly bit. */
152
153#ifndef __OS2__x
154 if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
155#else
156 if(os2_isattribute(path,aARCH)==0)
157#endif
158 result |= aARCH;
159
160#ifndef __OS2__x
161 if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
162#else
163 if(os2_isattribute(path,aSYSTEM)==0)
164#endif
165 result |= aSYSTEM;
166
167#ifndef __OS2__x
168 if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
169#else
170 if(os2_isattribute(path,aHIDDEN)==0)
171#endif
172
173 if (S_ISDIR(sbuf->st_mode))
174 result = aDIR | (result & aRONLY);
175
176 result |= set_sparse_flag(sbuf);
177
178#ifdef S_ISLNK
179#if LINKS_READ_ONLY
180 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
181 result |= aRONLY;
182#endif
183#endif
184
185 DEBUG(8,("dos_mode_from_sbuf returning "));
186
187 if (result & aHIDDEN) DEBUG(8, ("h"));
188 if (result & aRONLY ) DEBUG(8, ("r"));
189 if (result & aSYSTEM) DEBUG(8, ("s"));
190 if (result & aDIR ) DEBUG(8, ("d"));
191 if (result & aARCH ) DEBUG(8, ("a"));
192
193 DEBUG(8,("\n"));
194 return result;
195}
196
197/****************************************************************************
198 Get DOS attributes from an EA.
199****************************************************************************/
200
201static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
202{
203 ssize_t sizeret;
204 fstring attrstr;
205 unsigned int dosattr;
206
207 if (!lp_store_dos_attributes(SNUM(conn))) {
208 return False;
209 }
210
211 /* Don't reset pattr to zero as we may already have filename-based attributes we
212 need to preserve. */
213
214 sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
215 if (sizeret == -1) {
216 if (errno == ENOSYS
217#if defined(ENOTSUP)
218 || errno == ENOTSUP) {
219#else
220 ) {
221#endif
222#ifndef __OS2__
223 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
224 path, strerror(errno) ));
225#else
226 // HB On OS/2 no error in case of ./.. and errno == 2
227 if ((strncmp(path,"./..",4) != 0) || (errno != 2)) {
228 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
229 path, strerror(errno) ));
230
231 }
232#endif
233 set_store_dos_attributes(SNUM(conn), False);
234 }
235 return False;
236 }
237 /* Null terminate string. */
238 attrstr[sizeret] = 0;
239 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
240
241 if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
242 sscanf(attrstr, "%x", &dosattr) != 1) {
243 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
244 return False;
245 }
246
247 if (S_ISDIR(sbuf->st_mode)) {
248 dosattr |= aDIR;
249 }
250 *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
251
252 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
253
254 if (dosattr & aHIDDEN) DEBUG(8, ("h"));
255 if (dosattr & aRONLY ) DEBUG(8, ("r"));
256 if (dosattr & aSYSTEM) DEBUG(8, ("s"));
257 if (dosattr & aDIR ) DEBUG(8, ("d"));
258 if (dosattr & aARCH ) DEBUG(8, ("a"));
259
260 DEBUG(8,("\n"));
261
262 return True;
263}
264
265/****************************************************************************
266 Set DOS attributes in an EA.
267****************************************************************************/
268
269static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
270{
271 fstring attrstr;
272 files_struct *fsp = NULL;
273 bool ret = False;
274
275 if (!lp_store_dos_attributes(SNUM(conn))) {
276 return False;
277 }
278
279 snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
280 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
281 if((errno != EPERM) && (errno != EACCES)) {
282 if (errno == ENOSYS
283#if defined(ENOTSUP)
284 || errno == ENOTSUP) {
285#else
286 ) {
287#endif
288 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
289 path, strerror(errno) ));
290 set_store_dos_attributes(SNUM(conn), False);
291 }
292 return False;
293 }
294
295 /* We want DOS semantics, ie allow non owner with write permission to change the
296 bits on a file. Just like file_ntimes below.
297 */
298
299 /* Check if we have write access. */
300 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
301 return False;
302
303 /*
304 * We need to open the file with write access whilst
305 * still in our current user context. This ensures we
306 * are not violating security in doing the setxattr.
307 */
308
309 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
310 return ret;
311 become_root();
312 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
313 ret = True;
314 }
315 unbecome_root();
316 close_file_fchmod(fsp);
317 return ret;
318 }
319 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
320 return True;
321}
322
323/****************************************************************************
324 Change a unix mode to a dos mode for an ms dfs link.
325****************************************************************************/
326
327uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
328{
329 uint32 result = 0;
330
331 DEBUG(8,("dos_mode_msdfs: %s\n", path));
332
333 if (!VALID_STAT(*sbuf)) {
334 return 0;
335 }
336
337 /* First do any modifications that depend on the path name. */
338 /* hide files with a name starting with a . */
339 if (lp_hide_dot_files(SNUM(conn))) {
340 const char *p = strrchr_m(path,'/');
341 if (p) {
342 p++;
343 } else {
344 p = path;
345 }
346
347 /* Only . and .. are not hidden. */
348 if (p[0] == '.' && !((p[1] == '\0') ||
349 (p[1] == '.' && p[2] == '\0'))) {
350 result |= aHIDDEN;
351 }
352 }
353
354 result |= dos_mode_from_sbuf(conn, path, sbuf);
355
356 /* Optimization : Only call is_hidden_path if it's not already
357 hidden. */
358 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
359 result |= aHIDDEN;
360 }
361
362 DEBUG(8,("dos_mode_msdfs returning "));
363
364 if (result & aHIDDEN) DEBUG(8, ("h"));
365 if (result & aRONLY ) DEBUG(8, ("r"));
366 if (result & aSYSTEM) DEBUG(8, ("s"));
367 if (result & aDIR ) DEBUG(8, ("d"));
368 if (result & aARCH ) DEBUG(8, ("a"));
369 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
370
371 DEBUG(8,("\n"));
372
373 return(result);
374}
375
376/****************************************************************************
377 Change a unix mode to a dos mode.
378****************************************************************************/
379
380uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
381{
382 uint32 result = 0;
383 bool offline;
384
385 DEBUG(8,("dos_mode: %s\n", path));
386
387 if (!VALID_STAT(*sbuf)) {
388 return 0;
389 }
390
391 /* First do any modifications that depend on the path name. */
392 /* hide files with a name starting with a . */
393 if (lp_hide_dot_files(SNUM(conn))) {
394 const char *p = strrchr_m(path,'/');
395 if (p) {
396 p++;
397 } else {
398 p = path;
399 }
400
401 /* Only . and .. are not hidden. */
402 if (p[0] == '.' && !((p[1] == '\0') ||
403 (p[1] == '.' && p[2] == '\0'))) {
404 result |= aHIDDEN;
405 }
406 }
407
408 /* Get the DOS attributes from an EA by preference. */
409 if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
410 result |= set_sparse_flag(sbuf);
411 } else {
412 result |= dos_mode_from_sbuf(conn, path, sbuf);
413 }
414
415
416 offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf);
417 if (S_ISREG(sbuf->st_mode) && offline) {
418 result |= FILE_ATTRIBUTE_OFFLINE;
419 }
420
421 /* Optimization : Only call is_hidden_path if it's not already
422 hidden. */
423 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
424 result |= aHIDDEN;
425 }
426
427 DEBUG(8,("dos_mode returning "));
428
429 if (result & aHIDDEN) DEBUG(8, ("h"));
430 if (result & aRONLY ) DEBUG(8, ("r"));
431 if (result & aSYSTEM) DEBUG(8, ("s"));
432 if (result & aDIR ) DEBUG(8, ("d"));
433 if (result & aARCH ) DEBUG(8, ("a"));
434 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
435
436 DEBUG(8,("\n"));
437
438 return(result);
439}
440
441/*******************************************************************
442 chmod a file - but preserve some bits.
443********************************************************************/
444
445int file_set_dosmode(connection_struct *conn, const char *fname,
446 uint32 dosmode, SMB_STRUCT_STAT *st,
447 const char *parent_dir,
448 bool newfile)
449{
450 SMB_STRUCT_STAT st1;
451 int mask=0;
452 mode_t tmp;
453 mode_t unixmode;
454 int ret = -1, lret = -1;
455 uint32_t old_mode;
456
457 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
458 dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
459
460 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
461
462 if (st == NULL) {
463 SET_STAT_INVALID(st1);
464 st = &st1;
465 }
466
467 if (!VALID_STAT(*st)) {
468 if (SMB_VFS_STAT(conn,fname,st))
469 return(-1);
470 }
471
472 unixmode = st->st_mode;
473
474 get_acl_group_bits(conn, fname, &st->st_mode);
475
476 if (S_ISDIR(st->st_mode))
477 dosmode |= aDIR;
478 else
479 dosmode &= ~aDIR;
480
481 old_mode = dos_mode(conn,fname,st);
482
483 if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
484 if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
485 lret = SMB_VFS_SET_OFFLINE(conn, fname);
486 if (lret == -1) {
487 DEBUG(0, ("set_dos_mode: client has asked to set "
488 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
489 "an error while setting it or it is not supported.\n",
490 parent_dir, fname));
491 }
492 }
493 }
494
495 dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
496 old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
497
498 if (old_mode == dosmode) {
499 st->st_mode = unixmode;
500 return(0);
501 }
502
503 /* Store the DOS attributes in an EA by preference. */
504 if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
505 if (!newfile) {
506 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
507 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
508 }
509 st->st_mode = unixmode;
510 return 0;
511 }
512
513 unixmode = unix_mode(conn,dosmode,fname, parent_dir);
514
515 /* preserve the s bits */
516 mask |= (S_ISUID | S_ISGID);
517
518 /* preserve the t bit */
519#ifdef S_ISVTX
520 mask |= S_ISVTX;
521#endif
522
523 /* possibly preserve the x bits */
524 if (!MAP_ARCHIVE(conn))
525 mask |= S_IXUSR;
526 if (!MAP_SYSTEM(conn))
527 mask |= S_IXGRP;
528 if (!MAP_HIDDEN(conn))
529 mask |= S_IXOTH;
530
531 unixmode |= (st->st_mode & mask);
532
533 /* if we previously had any r bits set then leave them alone */
534 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
535 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
536 unixmode |= tmp;
537 }
538
539 /* if we previously had any w bits set then leave them alone
540 whilst adding in the new w bits, if the new mode is not rdonly */
541 if (!IS_DOS_READONLY(dosmode)) {
542 unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
543 }
544
545 ret = SMB_VFS_CHMOD(conn, fname, unixmode);
546 if (ret == 0) {
547 if(!newfile || (lret != -1)) {
548 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
549 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
550 }
551 st->st_mode = unixmode;
552 return 0;
553 }
554
555 if((errno != EPERM) && (errno != EACCES))
556 return -1;
557
558 if(!lp_dos_filemode(SNUM(conn)))
559 return -1;
560
561 /* We want DOS semantics, ie allow non owner with write permission to change the
562 bits on a file. Just like file_ntimes below.
563 */
564
565 /* Check if we have write access. */
566 if (CAN_WRITE(conn)) {
567 /*
568 * We need to open the file with write access whilst
569 * still in our current user context. This ensures we
570 * are not violating security in doing the fchmod.
571 * This file open does *not* break any oplocks we are
572 * holding. We need to review this.... may need to
573 * break batch oplocks open by others. JRA.
574 */
575 files_struct *fsp;
576 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
577 return -1;
578 become_root();
579 ret = SMB_VFS_FCHMOD(fsp, unixmode);
580 unbecome_root();
581 close_file_fchmod(fsp);
582 if (!newfile) {
583 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
584 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
585 }
586 if (ret == 0) {
587 st->st_mode = unixmode;
588 }
589 }
590
591 return( ret );
592}
593
594/*******************************************************************
595 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
596 than POSIX.
597*******************************************************************/
598
599int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
600{
601 SMB_STRUCT_STAT sbuf;
602 int ret = -1;
603
604 errno = 0;
605 ZERO_STRUCT(sbuf);
606
607 DEBUG(6, ("file_ntime: actime: %s",
608 time_to_asc(convert_timespec_to_time_t(ts[0]))));
609 DEBUG(6, ("file_ntime: modtime: %s",
610 time_to_asc(convert_timespec_to_time_t(ts[1]))));
611
612 /* Don't update the time on read-only shares */
613 /* We need this as set_filetime (which can be called on
614 close and other paths) can end up calling this function
615 without the NEED_WRITE protection. Found by :
616 Leo Weppelman <leo@wau.mis.ah.nl>
617 */
618
619 if (!CAN_WRITE(conn)) {
620 return 0;
621 }
622
623 if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
624 return 0;
625 }
626
627 if((errno != EPERM) && (errno != EACCES)) {
628 return -1;
629 }
630
631 if(!lp_dos_filetimes(SNUM(conn))) {
632 return -1;
633 }
634
635 /* We have permission (given by the Samba admin) to
636 break POSIX semantics and allow a user to change
637 the time on a file they don't own but can write to
638 (as DOS does).
639 */
640
641 /* Check if we have write access. */
642 if (can_write_to_file(conn, fname, &sbuf)) {
643 /* We are allowed to become root and change the filetime. */
644 become_root();
645 ret = SMB_VFS_NTIMES(conn, fname, ts);
646 unbecome_root();
647 }
648
649 return ret;
650}
651
652/******************************************************************
653 Force a "sticky" write time on a pathname. This will always be
654 returned on all future write time queries and set on close.
655******************************************************************/
656
657bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
658 struct file_id fileid, const struct timespec mtime)
659{
660 if (null_timespec(mtime)) {
661 return true;
662 }
663
664 if (!set_sticky_write_time(fileid, mtime)) {
665 return false;
666 }
667
668 return true;
669}
670
671/******************************************************************
672 Force a "sticky" write time on an fsp. This will always be
673 returned on all future write time queries and set on close.
674******************************************************************/
675
676bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
677{
678 fsp->write_time_forced = true;
679 TALLOC_FREE(fsp->update_write_time_event);
680
681 return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
682 fsp->file_id, mtime);
683}
684
685/******************************************************************
686 Update a write time immediately, without the 2 second delay.
687******************************************************************/
688
689bool update_write_time(struct files_struct *fsp)
690{
691 if (!set_write_time(fsp->file_id, timespec_current())) {
692 return false;
693 }
694
695 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
696 FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
697
698 return true;
699}
Note: See TracBrowser for help on using the repository browser.