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

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

Update 3.2 branch to 3.2.8

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