Consider an NTFS folder that has the explicit permissions Create Files / Write Data applied onto This Folder Only, and Create Folders / Append Data applied onto Files Only (and Read Attributes, because I understand that to be necessary).
> icacls x:\pathto\folder
x:\pathto\folder CONTOSO\Domain Users:(CI)(S,WD)
CONTOSO\Domain Users:(OI)(IO)(S,AD,REA,RA)
BUILTIN\Administrators:(I)(OI)(CI)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
In theory, this should allow a user to create a file if it doesn't exist, and append to a file if it does exist, but not otherwise overwrite or truncate the contents of the file, nor delete it.
Now, given that, how does one actually open that file for appending?
I've tried simple command-line/batch redirection:
> echo foo >> x:\pathto\folder\thefile.txt
> echo foo >> x:\pathto\folder\thefile.txt
Access denied.
...and VBScript
Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
Dim stream : Set stream = fso.OpenTextFile("x:\pathto\folder\thefile.txt", 8, True, 0) ' 8-ForAppending
stream.WriteLine("foo")
-----
> cscript writefoo.vbs //nologo //e:vbs
> cscript writefoo.vbs //nologo //e:vbs
Microsoft VBScript Runtime Error(2, 14): Permission denied
...and .NET (via PowerShell)
> (1..2) | %{
> Write-Host $_
> $f = [IO.File]::AppendText('x:\pathto\folder\thefile.txt')
> $f.WriteLine("foo")
> $f.Dispose()
> }
1
2
Exception calling "AppendText" with "1" argument(s): Access to the path "x:\pathto\folder\thefile.txt" is denied.
...and another .NET approach (again via PowerShell)
> (1..2) | %{
> Write-Host $_
> $f = [IO.File]::Open('x:\pathto\folder\thefile.txt', [IO.FileMode]::Append, [IO.FileAccess]::Write, [IO.FileShare]::None)
> $f = New-Object IO.StreamWriter -Arg $f
> $f.WriteLine("foo")
> $f.Dispose()
> }
1
2
Exception calling "Open" with "4" argument(s): Access to the path "x:\pathto\folder\thefile.txt" is denied.
In all cases, with Sysinternals Procmon running, I can see that the underlying CreateFile
is always made requesting Generic Write
for its permissions.
If I understand correctly, Generic Write
means Win32's FILE_GENERIC_WRITE
, which is a bitflag combination of FILE_APPEND_DATA | FILE_WRITE_DATA
(and others) which would require Create Files / Write Data on the file as well as the directory.
However, if I place Create Files / Write Data on the file, then files are no longer append-only -- they can't be deleted and re-written, but they can be truncated and rewritten -- which defeats the purpose.
So what mechanisms are available to me to open the file really, really for Append only?