pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patch to allow adding ACLs at file creation time, 2025-11-13
Posted by Anonymous on Thu 13th Nov 2025 01:01
raw | new post

  1. From f9636e8f43cbc064a059d68fa3f1be5611b578aa Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Thu, 13 Nov 2025 01:54:06 +0100
  4. Subject: [PATCH] daemon,nfs41_build_features.h,sys,tests: Allow atomically
  5.  adding ACLs at file/dir creation time
  6.  
  7. Allow atomically adding ACLs at file/dir creation time, as SMB/CIFS
  8. is able to do.
  9.  
  10. Note that this requires that the NFS server supports the |FATTR0_WORD0_ACL|
  11. attribute at file/dir creation time.
  12.  
  13. Reported-by: Aurelien Couderc <aurelien.couderc2002@gmail.com>
  14. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  15. ---
  16. daemon/acl.c                                  |   3 +-
  17.  daemon/open.c                                 |  90 ++++++++++
  18.  daemon/upcall.h                               |   4 +
  19.  nfs41_build_features.h                        |   6 +
  20.  sys/nfs41sys_driver.h                         |   4 +
  21.  sys/nfs41sys_openclose.c                      |  32 ++++
  22.  .../atomiccreatefilewithacl.ps1               | 159 ++++++++++++++++++
  23.  7 files changed, 297 insertions(+), 1 deletion(-)
  24.  create mode 100644 tests/atomiccreatefilewithacl/atomiccreatefilewithacl.ps1
  25.  
  26. diff --git a/daemon/acl.c b/daemon/acl.c
  27. index 8675db2..8fece12 100644
  28. --- a/daemon/acl.c
  29. +++ b/daemon/acl.c
  30. @@ -1219,7 +1219,8 @@ out:
  31.      return status;
  32.  }
  33.  
  34. -static int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  35. +/* FIXME: Move this into aclutils.c */
  36. +int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  37.      int file_type, bool named_attr_support, char *domain)
  38.  {
  39.      int status;
  40. diff --git a/daemon/open.c b/daemon/open.c
  41. index 5532e3c..93f8b3a 100644
  42. --- a/daemon/open.c
  43. +++ b/daemon/open.c
  44. @@ -326,6 +326,9 @@ static int parse_open(
  45.      nfs41_upcall *upcall)
  46.  {
  47.      int status;
  48. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  49. +    const void *sec_desc_ptr;
  50. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  51.      open_upcall_args *args = &upcall->args.open;
  52.  
  53.      status = get_name(&buffer, &length, &args->path);
  54. @@ -344,6 +347,14 @@ static int parse_open(
  55.      if (status) goto out;
  56.      status = safe_read(&buffer, &length, &args->create_opts, sizeof(ULONG));
  57.      if (status) goto out;
  58. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  59. +    status = safe_read(&buffer, &length, &args->sec_desc_len, sizeof(ULONG));
  60. +    if (status) goto out;
  61. +    status = get_safe_read_bufferpos(&buffer, &length,
  62. +        args->sec_desc_len, (const void **)&sec_desc_ptr);
  63. +    if (status) goto out;
  64. +    args->sec_desc = (PSECURITY_DESCRIPTOR)sec_desc_ptr;
  65. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  66.      status = safe_read(&buffer, &length, &args->disposition, sizeof(ULONG));
  67.      if (status) goto out;
  68.      status = safe_read(&buffer, &length, &args->open_owner_id, sizeof(LONG));
  69. @@ -751,6 +762,12 @@ out:
  70.  }
  71.  #endif /* NFS41_DRIVER_FEATURE_LOCAL_UIDGID_IN_NFSV3ATTRIBUTES */
  72.  
  73. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  74. +/* FIXME: Move this into aclutils.h */
  75. +int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
  76. +    int file_type, bool named_attr_support, char *domain);
  77. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  78. +
  79.  static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  80.  {
  81.      int status = 0;
  82. @@ -760,6 +777,14 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  83.      nfs41_file_info info = { 0 };
  84.      bool is_caseinsensitive_volume;
  85.  
  86. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  87. +    nfsacl41 create_nfs4_acl = {
  88. +        .flag = 0,
  89. +        .aces = NULL,
  90. +        .count = 0
  91. +    };
  92. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  93. +
  94.      switch (args->is_caseinsensitive_volume) {
  95.          case TRISTATE_BOOL_FALSE:
  96.              is_caseinsensitive_volume = false;
  97. @@ -819,6 +844,55 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  98.      else
  99.          state->type = NF4REG;
  100.  
  101. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  102. +    if (args->sec_desc_len) {
  103. +        PSID sid = NULL, gsid = NULL;
  104. +        BOOL sid_default, gsid_default;
  105. +        BOOL dacl_present, dacl_default;
  106. +        PACL acl;
  107. +        DPRINTF(0,
  108. +            ("handle_open: args->sec_desc=0x%p args->sec_desc_len=%ld\n",
  109. +            args->sec_desc, (long)args->sec_desc_len));
  110. +        status = GetSecurityDescriptorDacl(args->sec_desc, &dacl_present,
  111. +            &acl, &dacl_default);
  112. +        if (!status) {
  113. +            status = GetLastError();
  114. +            eprintf("handle_open: "
  115. +                "GetSecurityDescriptorDacl() failed, lasterr=%d\n",
  116. +                status);
  117. +            goto out;
  118. +        }
  119. +        status = GetSecurityDescriptorOwner(args->sec_desc,
  120. +            &sid, &sid_default);
  121. +        if (!status) {
  122. +            status = GetLastError();
  123. +            eprintf("handle_open: "
  124. +                "GetSecurityDescriptorOwner() failed, lasterr=%d\n",
  125. +                status);
  126. +            goto out;
  127. +        }
  128. +        status = GetSecurityDescriptorGroup(args->sec_desc,
  129. +            &gsid, &gsid_default);
  130. +        if (!status) {
  131. +            status = GetLastError();
  132. +            eprintf("handle_open: "
  133. +                "GetSecurityDescriptorOwner() failed, lasterr=%d\n",
  134. +                status);
  135. +            goto out;
  136. +        }
  137. +        status = map_dacl_2_nfs4acl(acl, sid, gsid, &create_nfs4_acl,
  138. +            state->type,
  139. +            false /* FIXME!! */,
  140. +            nfs41dg->localdomain_name);
  141. +        if (status) {
  142. +            eprintf("handle_open: "
  143. +                "map_dacl_2_nfs4acl() failed, status=%d\n",
  144. +                status);
  145. +            goto out;
  146. +        }
  147. +    }
  148. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  149. +
  150.      // always do a lookup
  151.      status = nfs41_lookup(upcall->root_ref, nfs41_root_session(upcall->root_ref),
  152.          is_caseinsensitive_volume, &state->path,
  153. @@ -988,6 +1062,12 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  154.          createattrs.attrmask.arr[0] = 0;
  155.          createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE;
  156.          createattrs.mode = 0777;
  157. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  158. +        if (create_nfs4_acl.aces) {
  159. +            createattrs.acl = &create_nfs4_acl;
  160. +            createattrs.attrmask.arr[0] |= FATTR4_WORD0_ACL;
  161. +        }
  162. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  163.  
  164.          DPRINTF(1, ("creating cygwin symlink '%s' -> '%s'\n",
  165.              state->file.name.name, args->symlink.path));
  166. @@ -1068,6 +1148,13 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  167.          createattrs.hidden = args->file_attrs & FILE_ATTRIBUTE_HIDDEN ? 1 : 0;
  168.          createattrs.system = args->file_attrs & FILE_ATTRIBUTE_SYSTEM ? 1 : 0;
  169.          createattrs.archive = args->file_attrs & FILE_ATTRIBUTE_ARCHIVE ? 1 : 0;
  170. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  171. +        if (create_nfs4_acl.aces) {
  172. +            createattrs.acl = &create_nfs4_acl;
  173. +            createattrs.attrmask.arr[0] |= FATTR4_WORD0_ACL;
  174. +        }
  175. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  176. +
  177.          /* FIXME: What about |FILE_ATTRIBUTE_OFFLINE| ? */
  178.  
  179.          map_access_2_allowdeny(args->access_mask, args->access_mode,
  180. @@ -1231,6 +1318,9 @@ create_chgrp_out:
  181.      upcall->state_ref = state;
  182.      nfs41_open_state_ref(upcall->state_ref);
  183.  out:
  184. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  185. +    free(create_nfs4_acl.aces);
  186. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  187.      return status;
  188.  out_free_state:
  189.      nfs41_open_state_deref(state);
  190. diff --git a/daemon/upcall.h b/daemon/upcall.h
  191. index 4d7afb6..5e78f54 100644
  192. --- a/daemon/upcall.h
  193. +++ b/daemon/upcall.h
  194. @@ -62,6 +62,10 @@ typedef struct __open_upcall_args {
  195.      ULONG file_attrs;
  196.      ULONG disposition;
  197.      ULONG create_opts;
  198. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  199. +    ULONG sec_desc_len;
  200. +    PSECURITY_DESCRIPTOR sec_desc;
  201. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  202.      LONG open_owner_id;
  203.      DWORD mode;
  204.  #ifdef NFS41_DRIVER_FEATURE_LOCAL_UIDGID_IN_NFSV3ATTRIBUTES
  205. diff --git a/nfs41_build_features.h b/nfs41_build_features.h
  206. index 94be0e2..fb744f5 100644
  207. --- a/nfs41_build_features.h
  208. +++ b/nfs41_build_features.h
  209. @@ -267,4 +267,10 @@
  210.   */
  211.  #define NFS41_DRIVER_HACK_ENABLE_PAGEFILE_SUPPORT 1
  212.  
  213. +/*
  214. + * |NFS41_DRIVER_ALLOW_CREATEFILE_ACLS| - allow setting
  215. + * ACLs at createfile time
  216. + */
  217. +#define NFS41_DRIVER_ALLOW_CREATEFILE_ACLS 1
  218. +
  219.  #endif /* !_NFS41_DRIVER_BUILDFEATURES_ */
  220. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  221. index ff9b82e..bf5ebc0 100644
  222. --- a/sys/nfs41sys_driver.h
  223. +++ b/sys/nfs41sys_driver.h
  224. @@ -235,6 +235,10 @@ typedef struct _updowncall_entry {
  225.              ULONG access_mode;
  226.              ULONG attrs;
  227.              ULONG copts;
  228. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  229. +            ULONG SdLength;
  230. +            PSECURITY_DESCRIPTOR SdBuffer;
  231. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  232.              ULONG disp;
  233.              ULONG cattrs;
  234.              LONG open_owner_id;
  235. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  236. index 9196aad..3247539 100644
  237. --- a/sys/nfs41sys_openclose.c
  238. +++ b/sys/nfs41sys_openclose.c
  239. @@ -124,6 +124,9 @@ NTSTATUS marshal_nfs41_open(
  240.          7 * sizeof(ULONG) +
  241.          1 * sizeof(BOOLEAN) +
  242.          2 * sizeof(HANDLE) +
  243. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  244. +        entry->u.Open.SdLength + 1 * sizeof(ULONG) +
  245. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  246.          length_as_utf8(&entry->u.Open.symlink);
  247.      if (header_len > buf_len) {
  248.          status = STATUS_INSUFFICIENT_RESOURCES;
  249. @@ -147,6 +150,14 @@ NTSTATUS marshal_nfs41_open(
  250.      tmp += sizeof(entry->u.Open.attrs);
  251.      RtlCopyMemory(tmp, &entry->u.Open.copts, sizeof(entry->u.Open.copts));
  252.      tmp += sizeof(entry->u.Open.copts);
  253. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  254. +    RtlCopyMemory(tmp, &entry->u.Open.SdLength, sizeof(entry->u.Open.SdLength));
  255. +    tmp += sizeof(entry->u.Open.SdLength);
  256. +    if (entry->u.Open.SdLength) {
  257. +        RtlCopyMemory(tmp, entry->u.Open.SdBuffer, entry->u.Open.SdLength);
  258. +        tmp += entry->u.Open.SdLength;
  259. +    }
  260. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  261.      RtlCopyMemory(tmp, &entry->u.Open.disp, sizeof(entry->u.Open.disp));
  262.      tmp += sizeof(entry->u.Open.disp);
  263.      RtlCopyMemory(tmp, &entry->u.Open.open_owner_id,
  264. @@ -644,6 +655,23 @@ NTSTATUS nfs41_Create(
  265.      status = check_nfs41_create_args(RxContext);
  266.      if (status) goto out;
  267.  
  268. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  269. +    ULONG SdLength = RxContext->Create.SdLength;
  270. +    PSECURITY_DESCRIPTOR SdBuffer;
  271. +    if (SdLength &&
  272. +        params->SecurityContext &&
  273. +        params->SecurityContext->AccessState) {
  274. +        SdBuffer = params->SecurityContext->AccessState->SecurityDescriptor;
  275. +    }
  276. +    else {
  277. +        SdBuffer = NULL;
  278. +    }
  279. +
  280. +    DbgP("nfs41_Create: "
  281. +        "SecurityDescriptor=0x%p, len=%lu\n",
  282. +        SdBuffer, SdLength);
  283. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  284. +
  285.      status = nfs41_UpcallCreate(NFS41_SYSOP_OPEN, NULL,
  286.          pVNetRootContext->session, INVALID_HANDLE_VALUE,
  287.          pNetRootContext->nfs41d_version,
  288. @@ -675,6 +703,10 @@ NTSTATUS nfs41_Create(
  289.          entry->u.Open.attrs |= FILE_ATTRIBUTE_ARCHIVE;
  290.      entry->u.Open.disp = params->Disposition;
  291.      entry->u.Open.copts = params->CreateOptions;
  292. +#ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  293. +    entry->u.Open.SdLength = SdLength;
  294. +    entry->u.Open.SdBuffer = SdBuffer;
  295. +#endif /* NFS41_DRIVER_ALLOW_CREATEFILE_ACLS */
  296.      entry->u.Open.srv_open = SrvOpen;
  297.      /* treat the NfsActOnLink ea as FILE_OPEN_REPARSE_POINT */
  298.      if ((ea && AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength)) ||
  299. diff --git a/tests/atomiccreatefilewithacl/atomiccreatefilewithacl.ps1 b/tests/atomiccreatefilewithacl/atomiccreatefilewithacl.ps1
  300. new file mode 100644
  301. index 0000000..1fb4e0b
  302. --- /dev/null
  303. +++ b/tests/atomiccreatefilewithacl/atomiccreatefilewithacl.ps1
  304. @@ -0,0 +1,159 @@
  305. +
  306. +#
  307. +# MIT License
  308. +#
  309. +# Copyright (c) 2025 Roland Mainz <roland.mainz@nrubsig.org>
  310. +#
  311. +# Permission is hereby granted, free of charge, to any person obtaining a copy
  312. +# of this software and associated documentation files (the "Software"), to deal
  313. +# in the Software without restriction, including without limitation the rights
  314. +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  315. +# copies of the Software, and to permit persons to whom the Software is
  316. +# furnished to do so, subject to the following conditions:
  317. +#
  318. +# The above copyright notice and this permission notice shall be included in all
  319. +# copies or substantial portions of the Software.
  320. +#
  321. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  322. +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  323. +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  324. +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  325. +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  326. +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  327. +# SOFTWARE.
  328. +#
  329. +
  330. +#
  331. +# atomiccreatefilewithacl.ps1 - Atomically create file and add ACL at create time
  332. +#
  333. +# powershell -Command "$( < /cygdrive/l/createacltest/atomiccreatefilewithacl.ps1 )"
  334. +#
  335. +
  336. +function New-FileWithAcl {
  337. +    [CmdletBinding()]
  338. +    param(
  339. +        [Parameter(Mandatory)]
  340. +        [string]$Path,
  341. +
  342. +        [Parameter(Mandatory)]
  343. +        [string]$Content,
  344. +
  345. +        # Zero or more user accounts (local or domain). e.g. "alice", "GLOBAL.LOC\bob"
  346. +        [string[]]$Users = @(),
  347. +
  348. +        # Zero or more group accounts (local or domain). e.g. "cygwingrp2", "GLOBAL.LOC\DevOps"
  349. +        [string[]]$Groups = @(),
  350. +
  351. +        # If set, disables inheritance and removes inherited ACEs.
  352. +        [switch]$DisableInheritance,
  353. +
  354. +        # If set, keeps inherited ACEs but prevents further propagation changes (uses Protect + Preserve)
  355. +        [switch]$ProtectAndPreserveInheritance
  356. +    )
  357. +
  358. +    begin {
  359. +        # Validate inheritance switches
  360. +        if ($DisableInheritance -and $ProtectAndPreserveInheritance) {
  361. +            throw "Use either -DisableInheritance or -ProtectAndPreserveInheritance, not both."
  362. +        }
  363. +
  364. +        # Ensure parent directory exists
  365. +        $dir = Split-Path -Path $Path -Parent
  366. +        if ([string]::IsNullOrWhiteSpace($dir)) {
  367. +            $dir = "."
  368. +        }
  369. +        if (-not (Test-Path -LiteralPath $dir)) {
  370. +            New-Item -ItemType Directory -Path $dir -Force | Out-Null
  371. +        }
  372. +
  373. +        # Helper: resolve an NTAccount (string) to a SID, with clear error if not found
  374. +        function Resolve-ToSid {
  375. +            param([Parameter(Mandatory)][string]$Account)
  376. +            try {
  377. +                $nt = New-Object System.Security.Principal.NTAccount($Account)
  378. +                return $nt.Translate([System.Security.Principal.SecurityIdentifier])
  379. +            }
  380. +            catch {
  381. +                throw "Account not found or not resolvable: '$Account'. Use 'DOMAIN\name' or '.\name' for local."
  382. +            }
  383. +        }
  384. +
  385. +        # Helper: create a FileSystemAccessRule (FullControl, file-only)
  386. +        function New-FullControlRule {
  387. +            param([Parameter(Mandatory)][System.Security.Principal.SecurityIdentifier]$Sid)
  388. +            return New-Object System.Security.AccessControl.FileSystemAccessRule(
  389. +                $Sid,
  390. +                [System.Security.AccessControl.FileSystemRights]::FullControl,
  391. +                [System.Security.AccessControl.InheritanceFlags]::None,       # file only
  392. +                [System.Security.AccessControl.PropagationFlags]::None,
  393. +                [System.Security.AccessControl.AccessControlType]::Allow
  394. +            )
  395. +        }
  396. +    }
  397. +
  398. +    process {
  399. +        # Build FileSecurity (DACL)
  400. +        $fileSec = New-Object System.Security.AccessControl.FileSecurity
  401. +
  402. +        # Inheritance behavior
  403. +        if ($DisableInheritance) {
  404. +            # protect: true, preserveInheritedACL: false (remove inherited ACEs)
  405. +            $fileSec.SetAccessRuleProtection($true, $false)
  406. +        }
  407. +        elseif ($ProtectAndPreserveInheritance) {
  408. +            # protect: true, preserveInheritedACL: true (keep existing inherited ACEs)
  409. +            $fileSec.SetAccessRuleProtection($true, $true)
  410. +        }
  411. +        else {
  412. +            # protect: false -> inherit from parent
  413. +            $fileSec.SetAccessRuleProtection($false, $true)
  414. +        }
  415. +
  416. +        # Add ACEs for users
  417. +        foreach ($u in $Users) {
  418. +            if ([string]::IsNullOrWhiteSpace($u)) { continue }
  419. +            $sid = Resolve-ToSid -Account $u
  420. +            $rule = New-FullControlRule -Sid $sid
  421. +            $fileSec.AddAccessRule($rule) | Out-Null
  422. +        }
  423. +
  424. +        # Add ACEs for groups
  425. +        foreach ($g in $Groups) {
  426. +            if ([string]::IsNullOrWhiteSpace($g)) { continue }
  427. +            $sid = Resolve-ToSid -Account $g
  428. +            $rule = New-FullControlRule -Sid $sid
  429. +            $fileSec.AddAccessRule($rule) | Out-Null
  430. +        }
  431. +
  432. +        # Create file atomically with the ACL
  433. +        $fs = $null
  434. +        $writer = $null
  435. +        try {
  436. +            $fs = [System.IO.File]::Create($Path, 4096, [System.IO.FileOptions]::None, $fileSec)
  437. +            $writer = New-Object System.IO.StreamWriter($fs)
  438. +            $writer.Write($Content)
  439. +            $writer.Flush()
  440. +        }
  441. +        finally {
  442. +            if ($writer) { $writer.Dispose() }
  443. +            if ($fs)     { $fs.Dispose() }
  444. +        }
  445. +
  446. +        # Return file info and ACL
  447. +        [PSCustomObject]@{
  448. +            Path = (Resolve-Path -LiteralPath $Path).ProviderPath
  449. +            Length = (Get-Item -LiteralPath $Path).Length
  450. +            Acl = (Get-Acl -LiteralPath $Path)
  451. +        }
  452. +    }
  453. +}
  454. +
  455. +# test 1
  456. +New-FileWithAcl `
  457. +  -Path "phw1.txt" `
  458. +  -Content "hello world" `
  459. +  -Users @("siegfried_wulsch", "roland_mainz") `
  460. +  -Groups @("cygwingrp2") `
  461. +  -DisableInheritance
  462. +
  463. +# EOF.
  464. --
  465. 2.51.0

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at