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

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

Update Samba 3.3 to 3.3.10 (source)

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