This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
return 0;
}
-/****************************************************************************
- Work out whether this file is offline
-****************************************************************************/
-
-#ifndef ISDOT
-#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0')
-#endif /* ISDOT */
-
-#ifndef ISDOTDOT
-#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0')
-#endif /* ISDOTDOT */
-
-static uint32 set_offline_flag(connection_struct *conn, const char *const path)
-{
- if (ISDOT(path) || ISDOTDOT(path)) {
- return 0;
- }
-
- if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
- return 0;
- }
-
- return dmapi_file_flags(path);
-}
-
/****************************************************************************
Change a dos mode to a unix mode.
Base permission for files:
Get DOS attributes from an EA.
****************************************************************************/
-static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
+static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
{
ssize_t sizeret;
fstring attrstr;
Set DOS attributes in an EA.
****************************************************************************/
-static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
+static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
{
fstring attrstr;
files_struct *fsp = NULL;
- BOOL ret = False;
+ bool ret = False;
if (!lp_store_dos_attributes(SNUM(conn))) {
return False;
}
/* We want DOS semantics, ie allow non owner with write permission to change the
- bits on a file. Just like file_utime below.
+ bits on a file. Just like file_ntimes below.
*/
/* Check if we have write access. */
uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
{
uint32 result = 0;
+ bool offline;
DEBUG(8,("dos_mode: %s\n", path));
result |= dos_mode_from_sbuf(conn, path, sbuf);
}
- if (S_ISREG(sbuf->st_mode)) {
- result |= set_offline_flag(conn, path);
+
+ offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf);
+ if (S_ISREG(sbuf->st_mode) && offline) {
+ result |= FILE_ATTRIBUTE_OFFLINE;
}
/* Optimization : Only call is_hidden_path if it's not already
int file_set_dosmode(connection_struct *conn, const char *fname,
uint32 dosmode, SMB_STRUCT_STAT *st,
- const char *parent_dir)
+ const char *parent_dir,
+ bool newfile)
{
SMB_STRUCT_STAT st1;
int mask=0;
mode_t tmp;
mode_t unixmode;
- int ret = -1;
+ int ret = -1, lret = -1;
+ uint32_t old_mode;
/* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
- dosmode &= SAMBA_ATTRIBUTES_MASK;
+ dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
- if (!st || (st && !VALID_STAT(*st))) {
+
+ if (st == NULL) {
+ SET_STAT_INVALID(st1);
st = &st1;
+ }
+
+ if (!VALID_STAT(*st)) {
if (SMB_VFS_STAT(conn,fname,st))
return(-1);
}
+ unixmode = st->st_mode;
+
get_acl_group_bits(conn, fname, &st->st_mode);
if (S_ISDIR(st->st_mode))
else
dosmode &= ~aDIR;
- if (dos_mode(conn,fname,st) == dosmode)
+ old_mode = dos_mode(conn,fname,st);
+
+ if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
+ if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
+ lret = SMB_VFS_SET_OFFLINE(conn, fname);
+ if (lret == -1) {
+ DEBUG(0, ("set_dos_mode: client has asked to set "
+ "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
+ "an error while setting it or it is not supported.\n",
+ parent_dir, fname));
+ }
+ }
+ }
+
+ dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
+ old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
+
+ if (old_mode == dosmode) {
+ st->st_mode = unixmode;
return(0);
+ }
/* Store the DOS attributes in an EA by preference. */
if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
+ if (!newfile) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+ }
+ st->st_mode = unixmode;
return 0;
}
unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
- if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) {
- notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES,
- NOTIFY_ACTION_MODIFIED);
+ ret = SMB_VFS_CHMOD(conn, fname, unixmode);
+ if (ret == 0) {
+ if(!newfile || (lret != -1)) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+ }
+ st->st_mode = unixmode;
return 0;
}
return -1;
/* We want DOS semantics, ie allow non owner with write permission to change the
- bits on a file. Just like file_utime below.
+ bits on a file. Just like file_ntimes below.
*/
/* Check if we have write access. */
if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
return -1;
become_root();
- ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
+ ret = SMB_VFS_FCHMOD(fsp, unixmode);
unbecome_root();
close_file_fchmod(fsp);
- notify_fname(conn, fname, FILE_NOTIFY_CHANGE_ATTRIBUTES,
- NOTIFY_ACTION_MODIFIED);
+ if (!newfile) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+ }
+ if (ret == 0) {
+ st->st_mode = unixmode;
+ }
}
return( ret );
}
/*******************************************************************
- Wrapper around dos_utime that possibly allows DOS semantics rather
+ Wrapper around the VFS ntimes that possibly allows DOS semantics rather
than POSIX.
*******************************************************************/
-int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times)
+int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
{
SMB_STRUCT_STAT sbuf;
int ret = -1;
errno = 0;
ZERO_STRUCT(sbuf);
+ DEBUG(6, ("file_ntime: actime: %s",
+ time_to_asc(convert_timespec_to_time_t(ts[0]))));
+ DEBUG(6, ("file_ntime: modtime: %s",
+ time_to_asc(convert_timespec_to_time_t(ts[1]))));
+
/* Don't update the time on read-only shares */
/* We need this as set_filetime (which can be called on
close and other paths) can end up calling this function
return 0;
}
- if(SMB_VFS_UTIME(conn,fname, times) == 0)
+ if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
return 0;
+ }
- if((errno != EPERM) && (errno != EACCES))
+ if((errno != EPERM) && (errno != EACCES)) {
return -1;
+ }
- if(!lp_dos_filetimes(SNUM(conn)))
+ if(!lp_dos_filetimes(SNUM(conn))) {
return -1;
+ }
/* We have permission (given by the Samba admin) to
break POSIX semantics and allow a user to change
if (can_write_to_file(conn, fname, &sbuf)) {
/* We are allowed to become root and change the filetime. */
become_root();
- ret = SMB_VFS_UTIME(conn,fname, times);
+ ret = SMB_VFS_NTIMES(conn, fname, ts);
unbecome_root();
}
return ret;
}
-
-/*******************************************************************
- Change a filetime - possibly allowing DOS semantics.
-*******************************************************************/
-BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
+/******************************************************************
+ Force a "sticky" write time on a pathname. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
+
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+ struct file_id fileid, const struct timespec mtime)
{
- struct utimbuf times;
+ if (null_timespec(mtime)) {
+ return true;
+ }
- if (null_mtime(mtime))
- return(True);
+ if (!set_sticky_write_time(fileid, mtime)) {
+ return false;
+ }
+
+ return true;
+}
- times.modtime = times.actime = mtime;
+/******************************************************************
+ Force a "sticky" write time on an fsp. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
- if (file_utime(conn, fname, ×)) {
- DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
- return False;
+bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
+{
+ fsp->write_time_forced = true;
+ TALLOC_FREE(fsp->update_write_time_event);
+
+ return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
+ fsp->file_id, mtime);
+}
+
+/******************************************************************
+ Update a write time immediately, without the 2 second delay.
+******************************************************************/
+
+bool update_write_time(struct files_struct *fsp)
+{
+ if (!set_write_time(fsp->file_id, timespec_current())) {
+ return false;
}
- notify_fname(conn, fname, FILE_NOTIFY_CHANGE_LAST_WRITE,
- NOTIFY_ACTION_MODIFIED);
-
- return(True);
-}
+ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
+
+ return true;
+}