summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h3
-rw-r--r--source3/smbd/dosmode.c49
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.