Zainspirowany walkami Craiga Landisa z DFSR (replikacją DFS) postanowiłem podłubać trochę w atrybutach plików. Niby nic niezwykłego. Plik może mieć atrybuty: Archive (FILE_ATTRIBUTE_ARCHIVE), ReadOnly (FILE_ATTRIBUTE_READONLY), System (FILE_ATTRIBUTE_SYSTEM) i Hidden (FILE_ATTRIBUTE_HIDDEN). Tak jest od czasów DOSa. Bardziej dociekliwi wiedzą również, że możliwy jest atrybut Directory (FILE_ATTRIBUTE_DIRECTORY) (wtedy taki plik jest specjalnie traktowany i światu objawia się jako folder) oraz Volume. Atrybut Volume zachowuje się dość dziwacznie, bo teoretycznie służy do oznaczania pliku jako nazwy wolumenu, ale w praktyce nie ma przeciwwskazań, żeby na jednym wolumenie takich plików były dziesiątki czy setki, w tym również w podkatalogach.
Od czasów DOSa trochę się zmieniło i wśród atrybutów znajdują się również typowe NTFSowe atrybuty takie jak Compressed, Sparse czy Encrypted i jeszcze kilka innych. Chętnym do głębszego zajrzenia polecam MSDN.
Warto zauważyć, że istnieje atrybut Normal (dokładniej FILE_ATTRIBUTE_NORMAL) którego sensowność w mojej opinii jest dość wątpliwa. Otóż atrybut ten oznacza, że plik nie ma żadnego innego atrybutu. Rzecz w tym, że wynikowe atrybuty pliku są sumą wartości poszczególnych atrybutów. Atrybut Normal (równy 0x00000080) oznacza więc dokładnie to samo, co brak jakiegokolwiek atrybutu czyli wartość 0x00000000. Co więcej, połączenie Normal z czymkolwiek innym oznacza, że atrybut Normal należy zignorować. Dziwne, ale tak już jest.
Wśród atrybutów ciekawych należy wymienić koniecznie atrybut Temp czyli FILE_ATTRIBUTE_TEMPORARY. Jeżeli utworzymy plik z takim atrybutem, to będzie on w specjalny sposób zoptymalizowany, przede wszystkim przez próbę przechowywania go w pamięci a nie na dysku. Fizycznie na dysk zostanie on zapisany dopiero po zamknięciu. Plik taki jest bardzo wygodny dla programistów, ponieważ mogą oni trzymać dane tymczasowe w pamięci, podczas gdy dostęp do nich wygląda jak dostęp do zwykłego pliku. Skoro programista decyduje się na użycie takiego atrybutu oznacza to, że plik powinien zapewniać szybki dostęp do danych w nim zawartych i że prawdopodobnie zostanie skasowany po wykorzystaniu. Ta ostatnia cecha ma szczególne znaczenie właśnie przy wspomnianym na początku DFSR. Dlaczego? Otóż dlatego, że DFSR nie zreplikuje takiego pliku! Nigdy, nigdzie i nie można tego zmienić! Z punktu widzenia programisty to naprawdę drobiazg. Wystarczy zmienić jeden bit i plik replikuje się bez problemu. Gorzej, gdy programista użył tego atrybutu przeczytawszy http://support.microsoft.com/kb/103237 "bo wtedy mu szybciej działa", a administrator nie ma o tym pojęcia i po prostu chce plik replikować razem z setkami czy tysiącami innych plików. Wszystko działa super, nie ma komunikatów o błędach, replikacja działa i tylko... ten jeden plik replikować się nie chce. Poniekąd to logiczne (w końcu to plik został oznaczony jako tymczasowy), niby prosto to zmienić... ale jak się nie wie o co chodzi, to znalezienie przyczyny "dziwnego" zachowania DFSR może zająć masę czasu. W szczegółowych logach tekstowych DFSR (debugowanie DFSR włączyć można zgodnie z http://support.microsoft.com/kb/958893 ) widać wpisy zawierające Skipping USN_RECORD with FILE_ATTRIBUTE_TEMPORARY flag, ale trzeba wiedzieć gdzie i czego szukać.
Pojawia się oczywiste pytanie, co zrobić jak już uda nam się znaleźć przyczynę problemów z replikacją. Rozwiązanie najprostsze (nakrzyczenie na programistę) nie zawsze jest wykonalne. Jeżeli przyczyną jest atrybut pliku, to może da się go zmienić? Oczywiście, że się da. Problem tkwi jednak w tym, że znane wszystkim polecenie attrib pozwala na wyświetlenie i zmianę pięciu atrybutów (R,A,S,H,I), ale tego akurat – nie.
Wyświetlić atrybuty można względnie prosto narzędziami wbudowanymi w system: fsutil usn readdata <nazwa_pliku>. Wynik działania zawiera pole File Attributes i wystarczy zrobić operację AND na wartości atrybutu oraz na wartości 0x00000100 odpowiedzialnej za oznaczenie pliku jako Temporary i sprawdzić czy wynik jest różny od zera. Dzięki temu można znaleźć winnego.
Nadal pozostaje jednak problem zmiany atrybutu. Jeżeli mamy pod ręką jakiegokolwiek programistę, może on dosłownie w kilka minut napisać prostą aplikację resetującą ten atrybut. Należy tylko pamiętać, że atrybut zmienia się na obiekcie PFSNODE związanym z danym plikiem przy pomocy metody SetAttributes. Jeżeli programisty pod ręką nie ma – najrozsądniej będzie użyć PowerShella. Wyświetlenie plików z atrybutami: Get-Childitem | Format-Table Name, Attributes Polecam testowe wykonanie tego polecenia w katalogu %temp% czyli %userprofile%\appdata\local\temp
Poszukiwania plików z atrybutem Temporary: Get-ChildItem <ścieżka> -force -recurse | Where-Object { $_.attributes -band 0x00000100 }
Atrybut usunąć można przy pomocy {$_.attributes = ($_.attributes -band 0xFFFFFEFF)} Stworzenie skryptu, który usunie atrybuty z wielu plików w podkatalogach polecam jako proste ćwiczenie.

Autor: Grzegorz Tworek