~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/smbd/dosmode.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
*/
20
20
 
21
21
#include "includes.h"
 
22
#include "system/filesys.h"
22
23
#include "librpc/gen_ndr/ndr_xattr.h"
 
24
#include "../libcli/security/security.h"
 
25
#include "smbd/smbd.h"
23
26
 
24
27
static uint32_t filter_mode_by_protocol(uint32_t mode)
25
28
{
33
36
        return mode;
34
37
}
35
38
 
36
 
static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
37
 
{
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;
41
 
        }
42
 
#endif
43
 
        return 0;
44
 
}
45
 
 
46
39
static int set_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf)
47
40
{
48
41
#ifdef S_ISLNK
49
42
#if LINKS_READ_ONLY
50
43
        if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
51
 
                return aRONLY;
 
44
                return FILE_ATTRIBUTE_READONLY;
52
45
#endif
53
46
#endif
54
47
        return 0;
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) {
183
 
                        result |= aRONLY;
 
176
                        result |= FILE_ATTRIBUTE_READONLY;
184
177
                }
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)) {
188
 
                        result |= aRONLY;
 
181
                        result |= FILE_ATTRIBUTE_READONLY;
189
182
                }
190
183
        } /* Else never set the readonly bit. */
191
184
 
192
185
        if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0))
193
 
                result |= aARCH;
 
186
                result |= FILE_ATTRIBUTE_ARCHIVE;
194
187
 
195
188
        if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0))
196
 
                result |= aSYSTEM;
 
189
                result |= FILE_ATTRIBUTE_SYSTEM;
197
190
 
198
191
        if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0))
199
 
                result |= aHIDDEN;   
 
192
                result |= FILE_ATTRIBUTE_HIDDEN;
200
193
 
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);
203
196
 
204
 
        result |= set_sparse_flag(&smb_fname->st);
205
197
        result |= set_link_read_only_flag(&smb_fname->st);
206
198
 
207
199
        DEBUG(8,("dos_mode_from_sbuf returning "));
208
200
 
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"));
214
206
 
215
207
        DEBUG(8,("\n"));
216
208
        return result;
249
241
#else
250
242
                                ) {
251
243
#endif
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;
263
255
 
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);
266
258
 
 
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)));
 
264
                return false;
 
265
        }
 
266
 
267
267
        DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n",
268
268
                  smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex));
269
269
 
281
281
                                update_stat_ex_create_time(&smb_fname->st,
282
282
                                                        create_time);
283
283
 
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,
304
304
                                                        create_time);
305
305
 
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)) ));
311
311
                        }
312
312
                        break;
313
 
                        default:
314
 
                                DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on "
315
 
                                         "file %s - %s\n", smb_fname_str_dbg(smb_fname),
316
 
                                         attrstr));
 
313
                default:
 
314
                        DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on "
 
315
                                 "file %s - %s\n", smb_fname_str_dbg(smb_fname),
 
316
                                 attrstr));
317
317
                        return false;
318
318
        }
319
319
 
320
320
        if (S_ISDIR(smb_fname->st.st_ex_mode)) {
321
 
                dosattr |= aDIR;
 
321
                dosattr |= FILE_ATTRIBUTE_DIRECTORY;
322
322
        }
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));
324
325
 
325
326
        DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
326
327
 
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"));
332
333
 
333
334
        DEBUG(8,("\n"));
334
335
 
347
348
        struct xattr_DOSATTRIB dosattrib;
348
349
        enum ndr_err_code ndr_err;
349
350
        DATA_BLOB blob;
350
 
        files_struct *fsp = NULL;
351
 
        bool ret = false;
352
351
 
353
352
        if (!lp_store_dos_attributes(SNUM(conn))) {
354
353
                return False;
364
363
        unix_timespec_to_nt_time(&dosattrib.info.info3.create_time,
365
364
                                smb_fname->st.st_ex_btime);
366
365
 
 
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) ));
 
370
 
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);
370
374
 
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,
383
387
                             0) == -1) {
 
388
                bool ret = false;
 
389
                files_struct *fsp = NULL;
 
390
 
384
391
                if((errno != EPERM) && (errno != EACCES)) {
385
392
                        if (errno == ENOSYS
386
393
#if defined(ENOTSUP)
413
420
 
414
421
                if (!NT_STATUS_IS_OK(open_file_fchmod(conn, smb_fname,
415
422
                                                      &fsp)))
416
 
                        return ret;
 
423
                        return false;
417
424
                become_root();
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) {
421
428
                        ret = true;
458
465
                /* Only . and .. are not hidden. */
459
466
                if (p[0] == '.' && !((p[1] == '\0') ||
460
467
                                (p[1] == '.' && p[2] == '\0'))) {
461
 
                        result |= aHIDDEN;
 
468
                        result |= FILE_ATTRIBUTE_HIDDEN;
462
469
                }
463
470
        }
464
471
 
466
473
 
467
474
        /* Optimization : Only call is_hidden_path if it's not already
468
475
           hidden. */
469
 
        if (!(result & aHIDDEN) &&
 
476
        if (!(result & FILE_ATTRIBUTE_HIDDEN) &&
470
477
            IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
471
 
                result |= aHIDDEN;
 
478
                result |= FILE_ATTRIBUTE_HIDDEN;
472
479
        }
473
480
 
474
481
        if (result == 0) {
479
486
 
480
487
        DEBUG(8,("dos_mode_msdfs returning "));
481
488
 
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]"));
488
495
 
489
496
        DEBUG(8,("\n"));
500
507
{
501
508
        uint32_t dos_stat_flags = 0;
502
509
 
503
 
        if (dosmode & aARCH)
 
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)));
534
541
 
535
542
        if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE)
536
 
                *dosmode |= aARCH;
 
543
                *dosmode |= FILE_ATTRIBUTE_ARCHIVE;
537
544
        if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN)
538
 
                *dosmode |= aHIDDEN;
 
545
                *dosmode |= FILE_ATTRIBUTE_HIDDEN;
539
546
        if (smb_fname->st.st_ex_flags & UF_DOS_RO)
540
 
                *dosmode |= aRONLY;
 
547
                *dosmode |= FILE_ATTRIBUTE_READONLY;
541
548
        if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM)
542
 
                *dosmode |= aSYSTEM;
 
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))
546
 
                *dosmode |= aDIR;
 
555
                *dosmode |= FILE_ATTRIBUTE_DIRECTORY;
547
556
 
548
 
        *dosmode |= set_sparse_flag(&smb_fname->st);
549
557
        *dosmode |= set_link_read_only_flag(&smb_fname->st);
550
558
 
551
559
        return true;
629
637
                /* Only . and .. are not hidden. */
630
638
                if (p[0] == '.' && !((p[1] == '\0') ||
631
639
                                (p[1] == '.' && p[2] == '\0'))) {
632
 
                        result |= aHIDDEN;
 
640
                        result |= FILE_ATTRIBUTE_HIDDEN;
633
641
                }
634
642
        }
635
643
 
638
646
#endif
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);
643
 
                } else {
 
649
                if (!get_ea_dos_attribute(conn, smb_fname, &result)) {
644
650
                        result |= dos_mode_from_sbuf(conn, smb_fname);
645
651
                }
646
652
        }
647
653
 
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;
651
657
        }
652
658
 
653
659
        /* Optimization : Only call is_hidden_path if it's not already
654
660
           hidden. */
655
 
        if (!(result & aHIDDEN) &&
 
661
        if (!(result & FILE_ATTRIBUTE_HIDDEN) &&
656
662
            IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
657
 
                result |= aHIDDEN;
 
663
                result |= FILE_ATTRIBUTE_HIDDEN;
658
664
        }
659
665
 
660
666
        if (result == 0) {
665
671
 
666
672
        DEBUG(8,("dos_mode returning "));
667
673
 
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]"));
674
680
 
675
681
        DEBUG(8,("\n"));
706
712
                           &smb_fname->st.st_ex_mode);
707
713
 
708
714
        if (S_ISDIR(smb_fname->st.st_ex_mode))
709
 
                dosmode |= aDIR;
 
715
                dosmode |= FILE_ATTRIBUTE_DIRECTORY;
710
716
        else
711
 
                dosmode &= ~aDIR;
 
717
                dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
712
718
 
713
719
        new_create_timespec = smb_fname->st.st_ex_btime;
714
720
 
716
722
 
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 "
806
812
 
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)));
814
820
                return -1;
815
821
        }
816
822
 
817
 
 
818
823
        ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
819
824
        if (ret == 0) {
820
825
                if(!newfile || (lret != -1)) {
864
869
        return( ret );
865
870
}
866
871
 
 
872
 
 
873
NTSTATUS file_set_sparse(connection_struct *conn,
 
874
                         files_struct *fsp,
 
875
                         bool sparse)
 
876
{
 
877
        uint32_t old_dosmode;
 
878
        uint32_t new_dosmode;
 
879
        NTSTATUS status;
 
880
 
 
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),
 
885
                        sparse,
 
886
                        lp_servicename(SNUM(conn))));
 
887
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
 
888
        }
 
889
 
 
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),
 
895
                        sparse,
 
896
                        fsp->access_mask));
 
897
                return NT_STATUS_ACCESS_DENIED;
 
898
        }
 
899
 
 
900
        DEBUG(10,("file_set_sparse: setting sparse bit %u on file %s\n",
 
901
                  sparse, smb_fname_str_dbg(fsp->fsp_name)));
 
902
 
 
903
        if (!lp_store_dos_attributes(SNUM(conn))) {
 
904
                return NT_STATUS_INVALID_DEVICE_REQUEST;
 
905
        }
 
906
 
 
907
        status = vfs_stat_fsp(fsp);
 
908
        if (!NT_STATUS_IS_OK(status)) {
 
909
                return status;
 
910
        }
 
911
 
 
912
        old_dosmode = dos_mode(conn, fsp->fsp_name);
 
913
 
 
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;
 
918
        } else {
 
919
                return NT_STATUS_OK;
 
920
        }
 
921
 
 
922
        /* Store the DOS attributes in an EA. */
 
923
        if (!set_ea_dos_attribute(conn, fsp->fsp_name,
 
924
                                  new_dosmode)) {
 
925
                if (errno == 0) {
 
926
                        errno = EIO;
 
927
                }
 
928
                return map_nt_error_from_unix(errno);
 
929
        }
 
930
 
 
931
        notify_fname(conn, NOTIFY_ACTION_MODIFIED,
 
932
                     FILE_NOTIFY_CHANGE_ATTRIBUTES,
 
933
                     fsp->fsp_name->base_name);
 
934
 
 
935
        fsp->is_sparse = sparse;
 
936
 
 
937
        return NT_STATUS_OK;
 
938
}
 
939
 
867
940
/*******************************************************************
868
941
 Wrapper around the VFS ntimes that possibly allows DOS semantics rather
869
942
 than POSIX.