diff options
-rw-r--r-- | source3/include/proto.h | 3 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 49 |
2 files changed, 52 insertions, 0 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 9b41321df6..53c1f5d370 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4620,6 +4620,9 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode); uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname); int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, uint32 dosmode, const char *parent_dir, bool newfile); +NTSTATUS file_set_sparse(connection_struct *conn, + struct smb_filename *smb_fname, + bool sparse); int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname, struct smb_file_time *ft); bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime); diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 2fafb15c6e..5d6e4b4760 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -846,6 +846,55 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, return( ret ); } + +NTSTATUS file_set_sparse(connection_struct *conn, + struct smb_filename *smb_fname, + bool sparse) +{ + SMB_STRUCT_STAT st; + uint32_t old_dosmode; + uint32_t new_dosmode; + + DEBUG(10,("file_set_sparse: setting sparse bit %u on file %s\n", + sparse, smb_fname_str_dbg(smb_fname))); + + if (!lp_store_dos_attributes(SNUM(conn))) { + return NT_STATUS_INVALID_DEVICE_REQUEST; + } + + SET_STAT_INVALID(st); + + if (SMB_VFS_STAT(conn, smb_fname)) { + return map_nt_error_from_unix(errno); + } + + old_dosmode = dos_mode(conn, smb_fname); + + if (sparse && !(old_dosmode & FILE_ATTRIBUTE_SPARSE)) { + new_dosmode = old_dosmode | FILE_ATTRIBUTE_SPARSE; + } else if (!sparse && (old_dosmode & FILE_ATTRIBUTE_SPARSE)) { + new_dosmode = old_dosmode & ~FILE_ATTRIBUTE_SPARSE; + } else { + return NT_STATUS_OK; + } + + /* Store the DOS attributes in an EA. */ + if (!set_ea_dos_attribute(conn, smb_fname, + new_dosmode)) { + if (errno == 0) { + errno = EIO; + } + return map_nt_error_from_unix(errno); + } + + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_ATTRIBUTES, + smb_fname->base_name); + + return NT_STATUS_OK; +} + + /******************************************************************* Wrapper around the VFS ntimes that possibly allows DOS semantics rather than POSIX. |