Onset: version control where nobody waits and nothing gets lost. The on command, its core and onset-server.
| 1 | # How Windows shows files' attributes to a process that sees Cloud Files |
| 2 | # placeholders as they are (as Git Bash's runtime asks to see them), and to |
| 3 | # one that doesn't, with each file's reparse tag. |
| 4 | # Usage: placeholders.ps1 [-ClearOffline] <path>... |
| 5 | # (-ClearOffline takes FILE_ATTRIBUTE_OFFLINE off each file first.) |
| $clear = $false |
| 7 | $paths = @() |
| 8 | foreach ($a in $args) { if ($a -eq '-ClearOffline') { $clear = $true } else { $paths += $a } } |
| 9 | Add-Type -TypeDefinition @' |
| 10 | using System; |
| 11 | using System.Runtime.InteropServices; |
| 12 | public static class Placeholders { |
| 13 | [DllImport("ntdll.dll")] public static extern sbyte RtlQueryProcessPlaceholderCompatibilityMode(); |
| 14 | [DllImport("ntdll.dll")] public static extern sbyte RtlSetProcessPlaceholderCompatibilityMode(sbyte mode); |
| 15 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern uint GetFileAttributesW(string path); |
| 16 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool SetFileAttributesW(string path, uint attributes); |
| 17 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] |
| 18 | public struct FindData { |
| 19 | public uint Attributes; |
| 20 | public uint C1, C2, A1, A2, W1, W2; |
| 21 | public uint SizeHigh, SizeLow, Reserved0, Reserved1; |
| 22 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string Name; |
| 23 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public string Alt; |
| 24 | } |
| 25 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr FindFirstFileW(string path, out FindData data); |
| 26 | [DllImport("kernel32.dll")] public static extern bool FindClose(IntPtr handle); |
| 27 | public static string Show(string path) { |
| 28 | FindData d; |
| 29 | IntPtr h = FindFirstFileW(path, out d); |
| 30 | string listed = ""; |
| 31 | if (h != new IntPtr(-1)) { FindClose(h); listed = String.Format(", listed {0:X8}, reparse tag {1:X8}", d.Attributes, d.Reserved0); } |
| 32 | return String.Format("{0:X8}{1}", GetFileAttributesW(path), listed); |
| 33 | } |
| 34 | public static string ClearOffline(string path) { |
| 35 | uint a = GetFileAttributesW(path); |
| 36 | uint keep = a & 0x2127; |
| 37 | bool ok = SetFileAttributesW(path, keep == 0 ? 0x80u : keep); |
| 38 | return ok ? "cleared" : "not cleared: error " + Marshal.GetLastWin32Error(); |
| 39 | } |
| 40 | } |
| 41 | '@ |
| 42 | "placeholder mode this process started with: $([Placeholders]::RtlQueryProcessPlaceholderCompatibilityMode())" |
| 43 | foreach ($p in $paths) { " as it sees $p : $([Placeholders]::Show($p))" } |
| 44 | [void][Placeholders]::RtlSetProcessPlaceholderCompatibilityMode(2) |
| 45 | "placeholder mode now (2 = exposed, as Git Bash's): $([Placeholders]::RtlQueryProcessPlaceholderCompatibilityMode())" |
| 46 | foreach ($p in $paths) { |
| 47 | if ($clear) { " offline $([Placeholders]::ClearOffline($p))" } |
| 48 | " as it sees $p : $([Placeholders]::Show($p))" |
| 49 | } |
| 50 |