source: branches/samba-3.3.x/source/smbd/dosmode.c@ 225

Last change on this file since 225 was 223, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 branch to 3.3.3

File size: 19.5 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__
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__
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__
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__
168 if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
169#else
170 if(os2_isattribute(path,aHIDDEN)==0)
171#endif
172 result |= aHIDDEN;
173
174 if (S_ISDIR(sbuf->st_mode))
175 result = aDIR | (result & aRONLY);
176
177 result |= set_sparse_flag(sbuf);
178
179#ifdef S_ISLNK
180#if LINKS_READ_ONLY
181 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
182 result |= aRONLY;
183#endif
184#endif
185
186 DEBUG(8,("dos_mode_from_sbuf returning "));
187
188 if (result & aHIDDEN) DEBUG(8, ("h"));
189 if (result & aRONLY ) DEBUG(8, ("r"));
190 if (result & aSYSTEM) DEBUG(8, ("s"));
191 if (result & aDIR ) DEBUG(8, ("d"));
192 if (result & aARCH ) DEBUG(8, ("a"));
193
194 DEBUG(8,("\n"));
195 return result;
196}
197
198/****************************************************************************
199 Get DOS attributes from an EA.
200****************************************************************************/
201
202static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
203{
204 ssize_t sizeret;
205 fstring attrstr;
206 unsigned int dosattr;
207
208 if (!lp_store_dos_attributes(SNUM(conn))) {
209 return False;
210 }
211
212 /* Don't reset pattr to zero as we may already have filename-based attributes we
213 need to preserve. */
214
215 sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
216 if (sizeret == -1) {
217 if (errno == ENOSYS
218#if defined(ENOTSUP)
219 || errno == ENOTSUP) {
220#else
221 ) {
222#endif
223 DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
224 path, strerror(errno) ));
225 set_store_dos_attributes(SNUM(conn), False);
226 }
227 return False;
228 }
229 /* Null terminate string. */
230 attrstr[sizeret] = 0;
231 DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
232
233 if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
234 sscanf(attrstr, "%x", &dosattr) != 1) {
235 DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
236 return False;
237 }
238
239 if (S_ISDIR(sbuf->st_mode)) {
240 dosattr |= aDIR;
241 }
242 *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
243
244 DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
245
246 if (dosattr & aHIDDEN) DEBUG(8, ("h"));
247 if (dosattr & aRONLY ) DEBUG(8, ("r"));
248 if (dosattr & aSYSTEM) DEBUG(8, ("s"));
249 if (dosattr & aDIR ) DEBUG(8, ("d"));
250 if (dosattr & aARCH ) DEBUG(8, ("a"));
251
252 DEBUG(8,("\n"));
253
254 return True;
255}
256
257/****************************************************************************
258 Set DOS attributes in an EA.
259****************************************************************************/
260
261static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
262{
263 fstring attrstr;
264 files_struct *fsp = NULL;
265 bool ret = False;
266
267 if (!lp_store_dos_attributes(SNUM(conn))) {
268 return False;
269 }
270
271 snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
272 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
273 if((errno != EPERM) && (errno != EACCES)) {
274 if (errno == ENOSYS
275#if defined(ENOTSUP)
276 || errno == ENOTSUP) {
277#else
278 ) {
279#endif
280 DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
281 path, strerror(errno) ));
282 set_store_dos_attributes(SNUM(conn), False);
283 }
284 return False;
285 }
286
287 /* We want DOS semantics, ie allow non owner with write permission to change the
288 bits on a file. Just like file_ntimes below.
289 */
290
291 /* Check if we have write access. */
292 if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
293 return False;
294
295 /*
296 * We need to open the file with write access whilst
297 * still in our current user context. This ensures we
298 * are not violating security in doing the setxattr.
299 */
300
301 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
302 return ret;
303 become_root();
304 if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
305 ret = True;
306 }
307 unbecome_root();
308 close_file_fchmod(fsp);
309 return ret;
310 }
311 DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
312 return True;
313}
314
315/****************************************************************************
316 Change a unix mode to a dos mode for an ms dfs link.
317****************************************************************************/
318
319uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
320{
321 uint32 result = 0;
322
323 DEBUG(8,("dos_mode_msdfs: %s\n", path));
324
325 if (!VALID_STAT(*sbuf)) {
326 return 0;
327 }
328
329 /* First do any modifications that depend on the path name. */
330 /* hide files with a name starting with a . */
331 if (lp_hide_dot_files(SNUM(conn))) {
332 const char *p = strrchr_m(path,'/');
333 if (p) {
334 p++;
335 } else {
336 p = path;
337 }
338
339 /* Only . and .. are not hidden. */
340 if (p[0] == '.' && !((p[1] == '\0') ||
341 (p[1] == '.' && p[2] == '\0'))) {
342 result |= aHIDDEN;
343 }
344 }
345
346 result |= dos_mode_from_sbuf(conn, path, sbuf);
347
348 /* Optimization : Only call is_hidden_path if it's not already
349 hidden. */
350 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
351 result |= aHIDDEN;
352 }
353
354 DEBUG(8,("dos_mode_msdfs returning "));
355
356 if (result & aHIDDEN) DEBUG(8, ("h"));
357 if (result & aRONLY ) DEBUG(8, ("r"));
358 if (result & aSYSTEM) DEBUG(8, ("s"));
359 if (result & aDIR ) DEBUG(8, ("d"));
360 if (result & aARCH ) DEBUG(8, ("a"));
361 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
362
363 DEBUG(8,("\n"));
364
365 return(result);
366}
367
368/****************************************************************************
369 Change a unix mode to a dos mode.
370****************************************************************************/
371
372uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
373{
374 uint32 result = 0;
375 bool offline;
376
377 DEBUG(8,("dos_mode: %s\n", path));
378
379 if (!VALID_STAT(*sbuf)) {
380 return 0;
381 }
382
383 /* First do any modifications that depend on the path name. */
384 /* hide files with a name starting with a . */
385 if (lp_hide_dot_files(SNUM(conn))) {
386 const char *p = strrchr_m(path,'/');
387 if (p) {
388 p++;
389 } else {
390 p = path;
391 }
392
393 /* Only . and .. are not hidden. */
394 if (p[0] == '.' && !((p[1] == '\0') ||
395 (p[1] == '.' && p[2] == '\0'))) {
396 result |= aHIDDEN;
397 }
398 }
399
400 /* Get the DOS attributes from an EA by preference. */
401 if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
402 result |= set_sparse_flag(sbuf);
403 } else {
404 result |= dos_mode_from_sbuf(conn, path, sbuf);
405 }
406
407
408 offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf);
409 if (S_ISREG(sbuf->st_mode) && offline) {
410 result |= FILE_ATTRIBUTE_OFFLINE;
411 }
412
413 /* Optimization : Only call is_hidden_path if it's not already
414 hidden. */
415 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
416 result |= aHIDDEN;
417 }
418
419 DEBUG(8,("dos_mode returning "));
420
421 if (result & aHIDDEN) DEBUG(8, ("h"));
422 if (result & aRONLY ) DEBUG(8, ("r"));
423 if (result & aSYSTEM) DEBUG(8, ("s"));
424 if (result & aDIR ) DEBUG(8, ("d"));
425 if (result & aARCH ) DEBUG(8, ("a"));
426 if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
427
428 DEBUG(8,("\n"));
429
430 return(result);
431}
432
433/*******************************************************************
434 chmod a file - but preserve some bits.
435********************************************************************/
436
437int file_set_dosmode(connection_struct *conn, const char *fname,
438 uint32 dosmode, SMB_STRUCT_STAT *st,
439 const char *parent_dir,
440 bool newfile)
441{
442 SMB_STRUCT_STAT st1;
443 int mask=0;
444 mode_t tmp;
445 mode_t unixmode;
446 int ret = -1, lret = -1;
447 uint32_t old_mode;
448
449 /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
450 dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
451
452 DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
453
454 if (st == NULL) {
455 SET_STAT_INVALID(st1);
456 st = &st1;
457 }
458
459 if (!VALID_STAT(*st)) {
460 if (SMB_VFS_STAT(conn,fname,st))
461 return(-1);
462 }
463
464 unixmode = st->st_mode;
465
466 get_acl_group_bits(conn, fname, &st->st_mode);
467
468 if (S_ISDIR(st->st_mode))
469 dosmode |= aDIR;
470 else
471 dosmode &= ~aDIR;
472
473 old_mode = dos_mode(conn,fname,st);
474
475 if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
476 if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
477 lret = SMB_VFS_SET_OFFLINE(conn, fname);
478 if (lret == -1) {
479 DEBUG(0, ("set_dos_mode: client has asked to set "
480 "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
481 "an error while setting it or it is not supported.\n",
482 parent_dir, fname));
483 }
484 }
485 }
486
487 dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
488 old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
489
490 if (old_mode == dosmode) {
491 st->st_mode = unixmode;
492 return(0);
493 }
494
495 /* Store the DOS attributes in an EA by preference. */
496 if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
497 if (!newfile) {
498 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
499 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
500 }
501 st->st_mode = unixmode;
502 return 0;
503 }
504
505 unixmode = unix_mode(conn,dosmode,fname, parent_dir);
506
507 /* preserve the s bits */
508 mask |= (S_ISUID | S_ISGID);
509
510 /* preserve the t bit */
511#ifdef S_ISVTX
512 mask |= S_ISVTX;
513#endif
514
515 /* possibly preserve the x bits */
516 if (!MAP_ARCHIVE(conn))
517 mask |= S_IXUSR;
518 if (!MAP_SYSTEM(conn))
519 mask |= S_IXGRP;
520 if (!MAP_HIDDEN(conn))
521 mask |= S_IXOTH;
522
523 unixmode |= (st->st_mode & mask);
524
525 /* if we previously had any r bits set then leave them alone */
526 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
527 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
528 unixmode |= tmp;
529 }
530
531 /* if we previously had any w bits set then leave them alone
532 whilst adding in the new w bits, if the new mode is not rdonly */
533 if (!IS_DOS_READONLY(dosmode)) {
534 unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
535 }
536
537 ret = SMB_VFS_CHMOD(conn, fname, unixmode);
538 if (ret == 0) {
539 if(!newfile || (lret != -1)) {
540 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
541 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
542 }
543 st->st_mode = unixmode;
544 return 0;
545 }
546
547 if((errno != EPERM) && (errno != EACCES))
548 return -1;
549
550 if(!lp_dos_filemode(SNUM(conn)))
551 return -1;
552
553 /* We want DOS semantics, ie allow non owner with write permission to change the
554 bits on a file. Just like file_ntimes below.
555 */
556
557 /* Check if we have write access. */
558 if (CAN_WRITE(conn)) {
559 /*
560 * We need to open the file with write access whilst
561 * still in our current user context. This ensures we
562 * are not violating security in doing the fchmod.
563 * This file open does *not* break any oplocks we are
564 * holding. We need to review this.... may need to
565 * break batch oplocks open by others. JRA.
566 */
567 files_struct *fsp;
568 if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
569 return -1;
570 become_root();
571 ret = SMB_VFS_FCHMOD(fsp, unixmode);
572 unbecome_root();
573 close_file_fchmod(fsp);
574 if (!newfile) {
575 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
576 FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
577 }
578 if (ret == 0) {
579 st->st_mode = unixmode;
580 }
581 }
582
583 return( ret );
584}
585
586/*******************************************************************
587 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
588 than POSIX.
589*******************************************************************/
590
591int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
592{
593 SMB_STRUCT_STAT sbuf;
594 int ret = -1;
595
596 errno = 0;
597 ZERO_STRUCT(sbuf);
598
599 DEBUG(6, ("file_ntime: actime: %s",
600 time_to_asc(convert_timespec_to_time_t(ts[0]))));
601 DEBUG(6, ("file_ntime: modtime: %s",
602 time_to_asc(convert_timespec_to_time_t(ts[1]))));
603
604 /* Don't update the time on read-only shares */
605 /* We need this as set_filetime (which can be called on
606 close and other paths) can end up calling this function
607 without the NEED_WRITE protection. Found by :
608 Leo Weppelman <leo@wau.mis.ah.nl>
609 */
610
611 if (!CAN_WRITE(conn)) {
612 return 0;
613 }
614
615 if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
616 return 0;
617 }
618
619 if((errno != EPERM) && (errno != EACCES)) {
620 return -1;
621 }
622
623 if(!lp_dos_filetimes(SNUM(conn))) {
624 return -1;
625 }
626
627 /* We have permission (given by the Samba admin) to
628 break POSIX semantics and allow a user to change
629 the time on a file they don't own but can write to
630 (as DOS does).
631 */
632
633 /* Check if we have write access. */
634 if (can_write_to_file(conn, fname, &sbuf)) {
635 /* We are allowed to become root and change the filetime. */
636 become_root();
637 ret = SMB_VFS_NTIMES(conn, fname, ts);
638 unbecome_root();
639 }
640
641 return ret;
642}
643
644/******************************************************************
645 Force a "sticky" write time on a pathname. This will always be
646 returned on all future write time queries and set on close.
647******************************************************************/
648
649bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
650 struct file_id fileid, const struct timespec mtime)
651{
652 if (null_timespec(mtime)) {
653 return true;
654 }
655
656 if (!set_sticky_write_time(fileid, mtime)) {
657 return false;
658 }
659
660 return true;
661}
662
663/******************************************************************
664 Force a "sticky" write time on an fsp. This will always be
665 returned on all future write time queries and set on close.
666******************************************************************/
667
668bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
669{
670 fsp->write_time_forced = true;
671 TALLOC_FREE(fsp->update_write_time_event);
672
673 return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
674 fsp->file_id, mtime);
675}
676
677/******************************************************************
678 Update a write time immediately, without the 2 second delay.
679******************************************************************/
680
681bool update_write_time(struct files_struct *fsp)
682{
683 if (!set_write_time(fsp->file_id, timespec_current())) {
684 return false;
685 }
686
687 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
688 FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
689
690 return true;
691}
Note: See TracBrowser for help on using the repository browser.