Розширені атрибути файлів у Windows

Розширені атрибути файлів — додатковий набір атрибутів, що підтримується Windows у файлових системах NTFS, FAT16 та HPFS. Розширені атрибути (extended attributes, EA) підтримуються починаючи з Windows NT і всіх наступних операційних системах на ядрі NT. Підтримка розширених атрибутів була додана до Windows для сумісності з операційною системою OS/2, в якій вони широко використовувалися. У Windows ці атрибути майже не використовуються програмним забезпеченням, але їх підтримка не була прибрана і присутня навіть у Windows 7.

Кожен розширений атрибут має рядок назви, максимальний розмір якого 255 символів та байт прапорів атрибута. Максимальний розмір даних розширеного атрибута - 64 кілобайти, причому це обмеження поширюється не на один окремий атрибут, а на всі атрибути.

У NTFS розширені атрибути причеплені до файлу як потоку ::$EA. Побачити цей потік у файлу можна за допомогою програми NTFS Stream Explorer. Вона призначена для роботи з альтернативними файловими потоками, але може відображати наявність потоку EA. На ілюстрації видно, що файл test.dat нульової довжини має потік розширених атрибутів розміром 23 байти.

Прочитати вміст потоку ::$EA безпосередньо не можна. Це приведе до висновку такого повідомлення:

У FAT16 для розширених атрибутів система створює корені диска системний файл «EA DATA. SF», там і зберігається їхній вміст. А ось у FAT32 підтримка розширених атрибутів відсутня, при копіюванні файлу на цю файлову систему EA губляться.

При копіюванні файлу з розширеними атрибутами на розділ FAT32 інформація EA мовчки втрачається. Windows не виводить жодних повідомлень про втрату інформації. Це відрізняє додаткові атрибути від подібних до концепціїальтернативних файлових потоків, підтримка яких є у NTFS. Наприклад у Windows 7 при спробі скопіювати з NTFS на FAT32 файл, що містить альтернативні потоки NTFS, виводиться повідомлення «Справді скопіювати файл без його властивостей?». Але якщо копіювати туди ж файл із EA, жодних повідомлень не буде.

Стандартних функцій WinAPI спеціально для роботи з розширеними атрибутами немає. Відсутні стандартні утиліти Windows для роботи з ними. Навіть утиліта fsutil, яка вміє робити багато цікавих операцій над файлами, не допоможе при роботі з EA. Цим пояснюється те, що ця технологія майже ніким не використовується у Windows. Читання розширених атрибутів можливе через використання функції BackupRead (спосіб описаний тут, але в прикладі описується читання потоків NTFS, а не EA) або через використання NT Native API (недокументованих функцій бібліотеки ntdll.dll).

Ім'я розширеного атрибуту складається з символів ASCII. Латинські літери наводяться до верхнього регістру, регістр символів не відрізняється при зверненні до атрибуту. Набір символів імені файлу не повинен містити заборонені символи: значення ASCII 0x00 - 0x1F, символи \ / : * ? " , + = [ ];. Максимальна довжина імені 255 символів.

API розширених атрибутів

У ntdll.dll містяться дві функції, за допомогою яких реалізується доступ до розширених атрибутів. Їхні прототипи:

Функція NtSetEaFile служить для запису інформації в розширені атрибути, а також видалення атрибутів. Функція NtQueryEaFile призначена для читання даних EA або перерахування розширених атрибутів файлу. Ці функції працюють зі структурою FILE_FULL_EA_INFORMATION, яка має наступний формат:

Поле NextEntryOffset містить усунення наступноїструктури у буфері даних. Поле потрібне при використанні NtQueryEaFile, коли вона повертає в буфер відразу кілька атрибутів. Поле Flags містить прапори атрибутів. За промовчанням поле прапорів має значення 0, припустимо також значення FILE_NEED_EA, що дорівнює 0x80, яке означає, що атрибут, що має цей прапор, важливий для обробки даних файлу.

Поля EaNameLength та EaValueLength – це розміри імені атрибута та даних атрибута. EaName це покажчик початку імені атрибута. Відразу після імені атрибута починаються дані. Загальний розмір структури FILE_FULL_EA_INFORMATION не може перевищувати 64 кб. За наявності буфері кількох структур їх загальний розмір також може перевищувати цей розмір.

Запис розширеного атрибуту

Визначимо у константі EA_BUF_LEN максимальний розмір буфера EA, що дорівнює 0xFFFF. Тоді максимальний розмір даних атрибуту MAX_EA_DATA_LEN дорівнює розміру буфера, від якого потрібно відібрати 8 (заголовок структури) і ще відібрати 2 (мінімально коротке ім'я атрибута, 1 літера + нульовий символ). Перед записом потрібно переконатися, що дані, що записуються, не перевищують цього значення.

Файл для запису даних EA потрібно відкрити з прапором FILE_FLAG_BACKUP_SEMANTICS. Далі слід сформувати структуру FILE_FULL_EA_INFORMATION, правильно вказати в ній розміри імені та даних, виставити прапори та скопіювати в структуру рядок імені та дані атрибуту за правильними зсувами.

Потім викликається функція NtSetEaFile і аналізується її значення NTSTATUS, що повертається. Внаслідок помилки спроби запису розширених атрибутів функція може повернути такі коди помилок:

Код помилки STATUS_EAS_NOT_SUPPORTED може означати як відсутність підтримки розширених атрибутів у файлової системи, а й неможливість використовувати EA в конкретного файла. Якщо файлє reparse дані, тобто файл є точкою повторної обробки (наприклад, симлінком), то такий файл розширені атрибути не підтримуються. У файловій системі NTFS файл не може одночасно бути і reparse point'ом, і містити розширені атрибути EA, тільки щось одне.

Читання розширеного атрибуту

Для читання розширеного атрибута слід отримати EA-буфер повністю і знайти в буфері ту структуру, яка містить атрибут з шуканим ім'ям (EaName). Буфер читається за допомогою функції NtQueryEaFile. Якщо параметр ReturnSingleEntry встановлений у TRUE, функція з кожним викликом повертає лише одну структуру, якщо FALSE — буфер пишуться відразу всі структури, а перехід між ними здійснюється через поле NextEntryOffset.

Дані читаються з буфера зі зміщення EaName + EaNameLength + 1. Параметр RestartScan перезапускає видачу атрибутів спочатку (якщо використовується ReturnSingleEntry). Параметр EaList може містити вказівник на додатковий список структур FILE_GET_EA_INFORMATION, який містить список EA, які потрібно отримати. Тим самим можна отримати в буфері не всі EA, а певний набір. Параметр EaIndex дозволяє звертатися до атрибута індексу.

Внаслідок помилки спроби читання розширених атрибутів, функція NtQueryEaFile може повернути такі коди помилок:

Код функції для читання розширених атрибутів:

Видалення розширеного атрибуту

Видалення розширеного атрибута з файлу реалізується через виклик NtSetEaFile, зі структурою, в якій поле EaValueLength дорівнює NULL, а EaName містить тільки ім'я атрибута, що видаляється.

Вихідний код

Завантажити консольну програму EA.EXE до роботи з розширеними атрибутами. В архіві міститься програма та її вихідний код на Сі.

Крім того,моя програма NTFS Stream Explorer, яка має графічний інтерфейс, також підтримує редагування розширених атрибутів файлів.