36
static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
38
#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
39
if (sbuf->st_ex_size > sbuf->st_ex_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
40
return FILE_ATTRIBUTE_SPARSE;
46
39
static int set_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf)
49
42
#if LINKS_READ_ONLY
50
43
if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
44
return FILE_ATTRIBUTE_READONLY;
180
173
if (ro_opts == MAP_READONLY_YES) {
181
174
/* Original Samba method - map inverse of user "w" bit. */
182
175
if ((smb_fname->st.st_ex_mode & S_IWUSR) == 0) {
176
result |= FILE_ATTRIBUTE_READONLY;
185
178
} else if (ro_opts == MAP_READONLY_PERMISSIONS) {
186
179
/* Check actual permissions for read-only. */
187
180
if (!can_write_to_file(conn, smb_fname)) {
181
result |= FILE_ATTRIBUTE_READONLY;
190
183
} /* Else never set the readonly bit. */
192
185
if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0))
186
result |= FILE_ATTRIBUTE_ARCHIVE;
195
188
if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0))
189
result |= FILE_ATTRIBUTE_SYSTEM;
198
191
if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0))
192
result |= FILE_ATTRIBUTE_HIDDEN;
201
194
if (S_ISDIR(smb_fname->st.st_ex_mode))
202
result = aDIR | (result & aRONLY);
195
result = FILE_ATTRIBUTE_DIRECTORY | (result & FILE_ATTRIBUTE_READONLY);
204
result |= set_sparse_flag(&smb_fname->st);
205
197
result |= set_link_read_only_flag(&smb_fname->st);
207
199
DEBUG(8,("dos_mode_from_sbuf returning "));
209
if (result & aHIDDEN) DEBUG(8, ("h"));
210
if (result & aRONLY ) DEBUG(8, ("r"));
211
if (result & aSYSTEM) DEBUG(8, ("s"));
212
if (result & aDIR ) DEBUG(8, ("d"));
213
if (result & aARCH ) DEBUG(8, ("a"));
201
if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h"));
202
if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r"));
203
if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s"));
204
if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d"));
205
if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a"));
252
DEBUG(1,("get_ea_dos_attributes: Cannot get attribute "
244
DEBUG(1,("get_ea_dos_attribute: Cannot get attribute "
253
245
"from EA on file %s: Error = %s\n",
254
246
smb_fname_str_dbg(smb_fname),
255
247
strerror(errno)));
261
253
blob.data = (uint8_t *)attrstr;
262
254
blob.length = sizeret;
264
ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &dosattrib,
256
ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib,
265
257
(ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB);
259
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
260
DEBUG(1,("get_ea_dos_attribute: bad ndr decode "
261
"from EA on file %s: Error = %s\n",
262
smb_fname_str_dbg(smb_fname),
263
ndr_errstr(ndr_err)));
267
267
DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n",
268
268
smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex));
281
281
update_stat_ex_create_time(&smb_fname->st,
284
DEBUG(10,("get_ea_dos_attributes: file %s case 1 "
284
DEBUG(10,("get_ea_dos_attribute: file %s case 1 "
285
285
"set btime %s\n",
286
286
smb_fname_str_dbg(smb_fname),
287
287
time_to_asc(convert_timespec_to_time_t(
303
303
update_stat_ex_create_time(&smb_fname->st,
306
DEBUG(10,("get_ea_dos_attributes: file %s case 3 "
306
DEBUG(10,("get_ea_dos_attribute: file %s case 3 "
307
307
"set btime %s\n",
308
308
smb_fname_str_dbg(smb_fname),
309
309
time_to_asc(convert_timespec_to_time_t(
310
310
create_time)) ));
314
DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on "
315
"file %s - %s\n", smb_fname_str_dbg(smb_fname),
314
DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on "
315
"file %s - %s\n", smb_fname_str_dbg(smb_fname),
320
320
if (S_ISDIR(smb_fname->st.st_ex_mode)) {
321
dosattr |= FILE_ATTRIBUTE_DIRECTORY;
323
*pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
323
/* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */
324
*pattr = (uint32)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
325
326
DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
327
if (dosattr & aHIDDEN) DEBUG(8, ("h"));
328
if (dosattr & aRONLY ) DEBUG(8, ("r"));
329
if (dosattr & aSYSTEM) DEBUG(8, ("s"));
330
if (dosattr & aDIR ) DEBUG(8, ("d"));
331
if (dosattr & aARCH ) DEBUG(8, ("a"));
328
if (dosattr & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h"));
329
if (dosattr & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r"));
330
if (dosattr & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s"));
331
if (dosattr & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d"));
332
if (dosattr & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a"));
364
363
unix_timespec_to_nt_time(&dosattrib.info.info3.create_time,
365
364
smb_fname->st.st_ex_btime);
366
DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n",
367
(unsigned int)dosmode,
368
time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)),
369
smb_fname_str_dbg(smb_fname) ));
367
371
ndr_err = ndr_push_struct_blob(
368
&blob, talloc_tos(), NULL, &dosattrib,
372
&blob, talloc_tos(), &dosattrib,
369
373
(ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB);
371
375
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
381
385
if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
382
386
SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length,
389
files_struct *fsp = NULL;
384
391
if((errno != EPERM) && (errno != EACCES)) {
385
392
if (errno == ENOSYS
386
393
#if defined(ENOTSUP)
414
421
if (!NT_STATUS_IS_OK(open_file_fchmod(conn, smb_fname,
418
if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
425
if (SMB_VFS_FSETXATTR(fsp,
419
426
SAMBA_XATTR_DOS_ATTRIB, blob.data,
420
427
blob.length, 0) == 0) {
467
474
/* Optimization : Only call is_hidden_path if it's not already
469
if (!(result & aHIDDEN) &&
476
if (!(result & FILE_ATTRIBUTE_HIDDEN) &&
470
477
IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
478
result |= FILE_ATTRIBUTE_HIDDEN;
474
481
if (result == 0) {
480
487
DEBUG(8,("dos_mode_msdfs returning "));
482
if (result & aHIDDEN) DEBUG(8, ("h"));
483
if (result & aRONLY ) DEBUG(8, ("r"));
484
if (result & aSYSTEM) DEBUG(8, ("s"));
485
if (result & aDIR ) DEBUG(8, ("d"));
486
if (result & aARCH ) DEBUG(8, ("a"));
489
if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h"));
490
if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r"));
491
if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s"));
492
if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d"));
493
if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a"));
487
494
if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
501
508
uint32_t dos_stat_flags = 0;
510
if (dosmode & FILE_ATTRIBUTE_ARCHIVE)
504
511
dos_stat_flags |= UF_DOS_ARCHIVE;
505
if (dosmode & aHIDDEN)
512
if (dosmode & FILE_ATTRIBUTE_HIDDEN)
506
513
dos_stat_flags |= UF_DOS_HIDDEN;
507
if (dosmode & aRONLY)
514
if (dosmode & FILE_ATTRIBUTE_READONLY)
508
515
dos_stat_flags |= UF_DOS_RO;
509
if (dosmode & aSYSTEM)
516
if (dosmode & FILE_ATTRIBUTE_SYSTEM)
510
517
dos_stat_flags |= UF_DOS_SYSTEM;
511
518
if (dosmode & FILE_ATTRIBUTE_NONINDEXED)
512
519
dos_stat_flags |= UF_DOS_NOINDEX;
533
540
smb_fname_str_dbg(smb_fname)));
535
542
if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE)
543
*dosmode |= FILE_ATTRIBUTE_ARCHIVE;
537
544
if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN)
545
*dosmode |= FILE_ATTRIBUTE_HIDDEN;
539
546
if (smb_fname->st.st_ex_flags & UF_DOS_RO)
547
*dosmode |= FILE_ATTRIBUTE_READONLY;
541
548
if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM)
549
*dosmode |= FILE_ATTRIBUTE_SYSTEM;
543
550
if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX)
544
551
*dosmode |= FILE_ATTRIBUTE_NONINDEXED;
552
if (smb_fname->st.st_ex_flags & FILE_ATTRIBUTE_SPARSE)
553
*dosmode |= FILE_ATTRIBUTE_SPARSE;
545
554
if (S_ISDIR(smb_fname->st.st_ex_mode))
555
*dosmode |= FILE_ATTRIBUTE_DIRECTORY;
548
*dosmode |= set_sparse_flag(&smb_fname->st);
549
557
*dosmode |= set_link_read_only_flag(&smb_fname->st);
639
647
if (!used_stat_dos_flags) {
640
648
/* Get the DOS attributes from an EA by preference. */
641
if (get_ea_dos_attribute(conn, smb_fname, &result)) {
642
result |= set_sparse_flag(&smb_fname->st);
649
if (!get_ea_dos_attribute(conn, smb_fname, &result)) {
644
650
result |= dos_mode_from_sbuf(conn, smb_fname);
648
offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &smb_fname->st);
654
offline = SMB_VFS_IS_OFFLINE(conn, smb_fname, &smb_fname->st);
649
655
if (S_ISREG(smb_fname->st.st_ex_mode) && offline) {
650
656
result |= FILE_ATTRIBUTE_OFFLINE;
653
659
/* Optimization : Only call is_hidden_path if it's not already
655
if (!(result & aHIDDEN) &&
661
if (!(result & FILE_ATTRIBUTE_HIDDEN) &&
656
662
IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
663
result |= FILE_ATTRIBUTE_HIDDEN;
660
666
if (result == 0) {
666
672
DEBUG(8,("dos_mode returning "));
668
if (result & aHIDDEN) DEBUG(8, ("h"));
669
if (result & aRONLY ) DEBUG(8, ("r"));
670
if (result & aSYSTEM) DEBUG(8, ("s"));
671
if (result & aDIR ) DEBUG(8, ("d"));
672
if (result & aARCH ) DEBUG(8, ("a"));
674
if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h"));
675
if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r"));
676
if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s"));
677
if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d"));
678
if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a"));
673
679
if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
706
712
&smb_fname->st.st_ex_mode);
708
714
if (S_ISDIR(smb_fname->st.st_ex_mode))
715
dosmode |= FILE_ATTRIBUTE_DIRECTORY;
717
dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
713
719
new_create_timespec = smb_fname->st.st_ex_btime;
717
723
if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
718
724
if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
719
lret = SMB_VFS_SET_OFFLINE(conn, smb_fname->base_name);
725
lret = SMB_VFS_SET_OFFLINE(conn, smb_fname);
720
726
if (lret == -1) {
721
727
DEBUG(0, ("set_dos_mode: client has asked to "
722
728
"set FILE_ATTRIBUTE_OFFLINE to "
807
813
if (S_ISDIR(smb_fname->st.st_ex_mode) && (unixmode & S_ISGID) &&
808
814
geteuid() != sec_initial_uid() &&
809
!current_user_in_group(smb_fname->st.st_ex_gid)) {
815
!current_user_in_group(conn, smb_fname->st.st_ex_gid)) {
810
816
DEBUG(3,("file_set_dosmode: setgid bit cannot be "
811
817
"set for directory %s\n",
812
818
smb_fname_str_dbg(smb_fname)));
873
NTSTATUS file_set_sparse(connection_struct *conn,
877
uint32_t old_dosmode;
878
uint32_t new_dosmode;
881
if (!CAN_WRITE(conn)) {
882
DEBUG(9,("file_set_sparse: fname[%s] set[%u] "
883
"on readonly share[%s]\n",
884
smb_fname_str_dbg(fsp->fsp_name),
886
lp_servicename(SNUM(conn))));
887
return NT_STATUS_MEDIA_WRITE_PROTECTED;
890
if (!(fsp->access_mask & FILE_WRITE_DATA) &&
891
!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
892
DEBUG(9,("file_set_sparse: fname[%s] set[%u] "
893
"access_mask[0x%08X] - access denied\n",
894
smb_fname_str_dbg(fsp->fsp_name),
897
return NT_STATUS_ACCESS_DENIED;
900
DEBUG(10,("file_set_sparse: setting sparse bit %u on file %s\n",
901
sparse, smb_fname_str_dbg(fsp->fsp_name)));
903
if (!lp_store_dos_attributes(SNUM(conn))) {
904
return NT_STATUS_INVALID_DEVICE_REQUEST;
907
status = vfs_stat_fsp(fsp);
908
if (!NT_STATUS_IS_OK(status)) {
912
old_dosmode = dos_mode(conn, fsp->fsp_name);
914
if (sparse && !(old_dosmode & FILE_ATTRIBUTE_SPARSE)) {
915
new_dosmode = old_dosmode | FILE_ATTRIBUTE_SPARSE;
916
} else if (!sparse && (old_dosmode & FILE_ATTRIBUTE_SPARSE)) {
917
new_dosmode = old_dosmode & ~FILE_ATTRIBUTE_SPARSE;
922
/* Store the DOS attributes in an EA. */
923
if (!set_ea_dos_attribute(conn, fsp->fsp_name,
928
return map_nt_error_from_unix(errno);
931
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
932
FILE_NOTIFY_CHANGE_ATTRIBUTES,
933
fsp->fsp_name->base_name);
935
fsp->is_sparse = sparse;
867
940
/*******************************************************************
868
941
Wrapper around the VFS ntimes that possibly allows DOS semantics rather