Atrybuty plików
Zainspirowany walkami Craiga Landisa z DFSR (replikacja DFS) postanowilem podlubac troche w atrybutach plików. Niby nic niezwyklego. Plik moze miec 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 wiedza równiez, ze mozliwy jest atrybut Directory (FILE_ATTRIBUTE_DIRECTORY) (wtedy taki plik jest specjalnie traktowany i swiatu objawia sie jako folder) oraz Volume. Atrybut Volume zachowuje sie dosc dziwacznie, bo teoretycznie sluzy do oznaczania pliku jako nazwy wolumenu, ale w praktyce nie ma przeciwwskazan, zeby na jednym wolumenie takich plików byly dziesiatki czy setki, w tym równiez w podkatalogach.
Od czasów DOSa troche sie zmienilo i wsród atrybutów znajduja sie równiez typowe NTFSowe atrybuty takie jak Compressed, Sparse czy Encrypted i jeszcze kilka innych. Chetnym do glebszego zajrzenia polecam MSDN.
Warto zauwazyc, ze istnieje atrybut Normal (dokladniej FILE_ATTRIBUTE_NORMAL) którego sensownosc w mojej opinii jest dosc watpliwa. Otóz atrybut ten oznacza, ze plik nie ma zadnego innego atrybutu. Rzecz w tym, ze wynikowe atrybuty pliku sa suma wartosci poszczególnych atrybutów. Atrybut Normal (równy 0x00000080) oznacza wiec dokladnie to samo, co brak jakiegokolwiek atrybutu czyli wartosc 0x00000000. Co wiecej, polaczenie Normal z czymkolwiek innym oznacza, ze atrybut Normal nalezy zignorowac. Dziwne, ale tak juz jest.
Wsród atrybutów ciekawych nalezy wymienic koniecznie atrybut Temp czyli FILE_ATTRIBUTE_TEMPORARY. Jezeli utworzymy plik z takim atrybutem, to bedzie on w specjalny sposób zoptymalizowany, przede wszystkim przez próbe przechowywania go w pamieci a nie na dysku. Fizycznie na dysk zostanie on zapisany dopiero po zamknieciu. Plik taki jest bardzo wygodny dla programistów, poniewaz moga oni trzymac dane tymczasowe w pamieci, podczas gdy dostep do nich wyglada jak dostep do zwyklego pliku. Skoro programista decyduje sie na uzycie takiego atrybutu oznacza to, ze plik powinien zapewniac szybki dostep do danych w nim zawartych i ze prawdopodobnie zostanie skasowany po wykorzystaniu. Ta ostatnia cecha ma szczególne znaczenie wlasnie przy wspomnianym na poczatku DFSR. Dlaczego? Otóz dlatego, ze DFSR nie zreplikuje takiego pliku! Nigdy, nigdzie i nie mozna tego zmienic! Z punktu widzenia programisty to naprawde drobiazg. Wystarczy zmienic jeden bit i plik replikuje sie bez problemu. Gorzej, gdy programista uzyl tego atrybutu przeczytawszy https://support.microsoft.com/kb/103237 "bo wtedy mu szybciej dziala", a administrator nie ma o tym pojecia i po prostu chce plik replikowac razem z setkami czy tysiacami innych plików. Wszystko dziala super, nie ma komunikatów o bledach, replikacja dziala i tylko... ten jeden plik replikowac sie nie chce. Poniekad to logiczne (w koncu to plik zostal oznaczony jako tymczasowy), niby prosto to zmienic... ale jak sie nie wie o co chodzi, to znalezienie przyczyny "dziwnego" zachowania DFSR moze zajac mase czasu. W szczególowych logach tekstowych DFSR (debugowanie DFSR wlaczyc mozna zgodnie z https://support.microsoft.com/kb/958893 ) widac wpisy zawierajace Skipping USN_RECORD with FILE_ATTRIBUTE_TEMPORARY flag, ale trzeba wiedziec gdzie i czego szukac.
Pojawia sie oczywiste pytanie, co zrobic jak juz uda nam sie znalezc przyczyne problemów z replikacja. Rozwiazanie najprostsze (nakrzyczenie na programiste) nie zawsze jest wykonalne. Jezeli przyczyna jest atrybut pliku, to moze da sie go zmienic? Oczywiscie, ze sie da. Problem tkwi jednak w tym, ze znane wszystkim polecenie attrib pozwala na wyswietlenie i zmiane pieciu atrybutów (R,A,S,H,I), ale tego akurat – nie.
Wyswietlic atrybuty mozna wzglednie prosto narzedziami wbudowanymi w system: fsutil usn readdata <nazwa_pliku> . Wynik dzialania zawiera pole File Attributes i wystarczy zrobic operacje AND na wartosci atrybutu oraz na wartosci 0x00000100 odpowiedzialnej za oznaczenie pliku jako Temporary i sprawdzic czy wynik jest rózny od zera. Dzieki temu mozna znalezc winnego.
Nadal pozostaje jednak problem zmiany atrybutu. Jezeli mamy pod reka jakiegokolwiek programiste, moze on doslownie w kilka minut napisac prosta aplikacje resetujaca ten atrybut. Nalezy tylko pamietac, ze atrybut zmienia sie na obiekcie PFSNODE zwiazanym z danym plikiem przy pomocy metody SetAttributes. Jezeli programisty pod reka nie ma – najrozsadniej bedzie uzyc PowerShella. Wyswietlenie 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 <sciezka> -force -recurse | Where-Object { $_.attributes -band 0x00000100 }
Atrybut usunac mozna przy pomocy {$_.attributes = ($_.attributes -band 0xFFFFFEFF)} Stworzenie skryptu, który usunie atrybuty z wielu plików w podkatalogach polecam jako proste cwiczenie.
Autor: Grzegorz Tworek