mode_t tmp;
mode_t unixmode;
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));
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);
}
unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
- if (dosmode & 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));
- }
- }
-
ret = SMB_VFS_CHMOD(conn, fname, unixmode);
if (ret == 0) {
if(!newfile || (lret != -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 ret;
}
-/*******************************************************************
- Change a filetime - possibly allowing DOS semantics.
-*******************************************************************/
+/******************************************************************
+ 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_filetime(connection_struct *conn, const char *fname,
- const struct timespec mtime)
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+ struct file_id fileid, const struct timespec mtime)
{
- struct timespec ts[2];
-
if (null_timespec(mtime)) {
- return(True);
+ return true;
}
- ts[1] = mtime; /* mtime. */
- ts[0] = ts[1]; /* atime. */
+ if (!set_sticky_write_time(fileid, mtime)) {
+ return false;
+ }
- if (file_ntimes(conn, fname, ts)) {
- DEBUG(4,("set_filetime(%s) failed: %s\n",
- fname,strerror(errno)));
- return False;
+ return true;
+}
+
+/******************************************************************
+ Force a "sticky" write time on an fsp. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
+
+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, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
return true;
}