Файловая система FAT 16
Хранение файлов, доступ к ним, установка и изменение атрибутов. Операционные системы DOS, Windows 95/98/Me, Windows NT/2000/XP. Файловая система FAT 16. Уменьшение потерь дискового пространства. Количество секторов в кластере. Главная загрузочная запись.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | реферат |
Язык | русский |
Дата добавления | 19.01.2012 |
Размер файла | 72,9 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Содержание
- Введение
- Файловая система, определение, общие сведения
- Файловая система FAT, немного истории
- Файловая система FAT 16
- Структура FAT
- Общая информация
- Главная загрузочная запись (MBR)
- Загрузочная запись раздела (PBR)
- Записи FAT
- Записи каталога
- Область данных (кластер 0)
- Литература
- Введение
- Трудно назвать другую сферу человеческой, которая развивалась бы столь стремительно и порождала бы такое разнообразие проблем, как информатизация и компьютеризация общества. История развития информационных технологий характеризуется быстрым изменением концептуальных представлений, технических средств, методов и сфер их применения.
- В современных реалиях весьма актуальным для большинства людей стало умение пользоваться промышленными информационными технологиями. Проникновение компьютеров во все сферы жизни общества убеждает в том, что культура общения с компьютером становится общей культуры человека.
- Основной единицей хранения информации является файл - однородный набор данных, характеризуемый рядом свойств (атрибутов).
- Файловая система является фундаментом, на котором лежит любая современная ОС, так как в файлах хранятся программы и библиотеки ОС, программы и данные пользователя.
- Файловая система обеспечивает хранение файлов, доступ к ним, установку и изменение атрибутов (свойств) файлов, различные операции с файлами.
- Информация хранится в файлах, организованных определенным образом и расположенных на физическом носителе информации.
- Существует множество реализаций файловых систем. Часто операционная система имеет собственную реализацию файловой системы.
- Целью данной работы является анализ файловой системы FAT 16.
- В данной работе будут описаны такие понятия, как файловая система и кластер, описано историческое развитие FAT, и рассмотрена структура файловой системы FAT 16
- Информационными основами для этой работы послужили учебные и справочные пособия по предмету «Операционные системы», материалы веб-сайтов и Интернет изданий.
Файловая система, определение, общие сведения
Файловая система - это структура, с помощью которой ядро операционной системы, предоставляет пользователям и процессам ресурсы долговременной памяти системы, то есть памяти на долговременных носителях информации - жестких и гибких дисках, CD-ROM, магнитных лентах и т.д.
Файловая система представляет информацию на диске в виде совокупности файлов и папок. С точки зрения пользователя, файл - это единица хранения логически связанной информации: текстовой, графической, звуковой, видео. С точки зрения организации хранения данных на диске, файл - это цепочка связанных между собой кластеров. Такая организация характерна для файловых систем, поддерживаемых разными версиями Windows.
Кластер - это минимальная единица хранения информации.
Каждый кластер содержит фиксированное количество секторов: 1, 2, 4, 8, 16, 32, то есть кратное степени двойки. Точное значение количества секторов в кластере зависит от размера раздела. Чем больше размер раздела, тем больше секторов содержится в кластере. Размер каждого сектора на любом диске строго фиксирован, обычно 512 байт. Каждый кластер имеет свой номер, причем, нумерация начинается с 2.
Из выше сказанного понятно, что операционная система отводит место для файлов на диске участками, которые называются кластерами. Каждый файл, в зависимости от размера, получает для хранения своих данных один или несколько кластеров, которые могут располагаться подряд, один за другим или же в разброс по всему диску. Свободные кластеры выделяются для файла по мере необходимости, это когда фактически выполняется запись на диск. Что избавляет пользователя от необходимости заранее резервировать место для каждого файла и знать, где именно на диске хранится тот или иной файл. Все операции выделения файлам свободных кластеров и записи в них данных выполняются системой автоматически, без участия пользователя. Каждому файлу присваивается уникальное имя, по которому пользователь, а точнее программы, с которыми работает пользователь, могут обращаться к файлу. Для удобства хранения файлы группируются в папках.
Операционная система обеспечивает возможность работы пользователя с данными, поддерживая на разделах диска ту или иную файловую систему. Каждая операционная система может работать с одной или несколькими файловыми системами. Все файловые системы включают таблицу расположения файлов, папки и файлы и выполняют следующие основные функции:
· Отслеживание занятого и свободного пространства на диске, а также дефектных секторов;
· Поддержка папок и имен файлов;
· Отслеживание физического расположения файлов на диске.
В настоящее время наиболее распространенными на персональных компьютерах являются три файловые системы:
· FAT16 - в DOS, Windows 95?98?Me, Windows NT?2000?XP;
· FAT32 - в Windows 95OSR2?98?Me, Windows NT?2000?XP;
· NTFS - в Windows NT?2000?XP.
Файловая система FAT, немного истории
Файловая система FAT (File Access Table - таблица размещения файлов) является простейшей файловой системой, разработанной для небольших дисков и простых структур каталогов. Ее название происходит от названия метода, применяемого для организации файлов - таблица размещения файлов. Система FAT используемая в Windows, устанавливает размер блоков данных, передаваемых диском, в соответствии с размером кластера в DOS. Как и во многих других файловых системах, в FAT не предусмотрено распределение пространства на диске таким образом, чтобы оно точно соответствовало объему файлов. Вместо этого дисковое пространство делится на элементы, называемые кластерами. Размер кластера изменяется в зависимости от типа и размера диска. Обычно размеры кластеров невелики, и этот фактор не является определяющим для производительности системы. А величина кластеров HDD (FAT16) может в значительной мере повлиять на ее быстродействие.
В модификации FAT-а предусмотрено увеличение размера записи с 16 до 32 битов (FAT32) Это позволяет адресовать и размещать большее количество кластеров на диске.
FAT файловая система была впервые введена во времена MS-DOS в далеком 1981 году. Цель таблицы размещения файлов заключается в обеспечении соответствия между кластерами и физическое расположение данных в терминах цилиндров, дорожек и секторов - форма обращения использовались аппаратно контроллер диска.
Первое воплощение FAT был известен как FAT12, которая поддерживается максимальный размер раздела 8 МБ. Это было заменено в 1984 году FAT16, который увеличил максимальный размер раздела до 2 Гб. FAT16 претерпел ряд незначительных изменений на протяжении многих лет, например, что позволяет ей обрабатывать имена файлов длиннее оригинального ограничение в 8,3 символов. Основные ограничения FAT16 является то, что она накладывает фиксированных максимальное количество кластеров на раздел, а это означает, что чем больше жесткий диск, тем больше размер кластера и более непригодным для использования места на диске. Самым большим преимуществом FAT16 является то, что она совместима через широкий спектр операционных систем, включая Windows.
В таблице приводится сравнение объема и размера кластера по умолчанию для различных файловых систем Windows, до сих пор широко используется:
Размер тома |
FAT16 |
FAT32 |
NTFS |
|
Размер кластера |
Размер кластера |
Размер кластера |
||
7 МБ - 16 МБ |
2KB |
Не поддерживается |
512 байт |
|
17MB - 32 Мб |
512 байт |
Не поддерживается |
512 байт |
|
33 Мб - 64 Мб |
1 КБ |
512 байт |
512 байт |
|
65MB - 128MB |
2KB |
1 КБ |
512 байт |
|
129MB - 256 Мб |
4KB |
2KB |
512 байт |
|
257MB - 512 Мб |
8KB |
4KB |
512 байт |
|
513MB - 1GB |
16KB |
4KB |
1 КБ |
|
1GB - 2GB |
32KB |
4KB |
2KB |
|
2Гб - 4Гб |
64KB |
4KB |
4KB |
|
4GB - 8GB |
Не поддерживается |
4KB |
4KB |
|
8 Гб - 16 Гб |
Не поддерживается |
8KB |
4KB |
|
16 ГБ - 32 ГБ |
Не поддерживается |
16KB |
4KB |
|
32 Гб - 2 Тб |
Не поддерживается |
Не поддерживается |
4KB |
Файловая система FAT 16
Файловая система FAT 16, являющаяся основной для операционных систем DOS, Windows 95?98?Me, Windows NT?2000?XP, а также поддерживается большинством других систем. FAT 16 представляет собой простую файловую систему, разработанную для небольших дисков и простых структур каталогов. Таблица размещается в начале диска. Число 16 означает, что данная файловая система 16-разрядная - для адресации кластеров используется 16 разрядов. Операционная система использует Таблицу размещения файлов для поиска файла и определения кластеров, которые этот файл занимает на жестком диске. Кроме того, в Таблице фиксируются сведения о свободных и дефектных кластерах. (Чтобы легче было осмыслить файловую систему FAT16 её можно представить в виде оглавления книги и работы с этим оглавлением, вот именно также операционная система работает с FAT 16)
Чтобы прочитать файл, операционная система должна найти по имени файла запись в папке и прочитать номер первого кластера файла. Первый кластер представляет собой начало файла. Затем необходимо прочитать соответствующий первому кластеру файла элемент FAT. Если элемент содержит метку - последний в цепочке, то дальше ни чего искать не нужно: весь файл умещается в одном кластере. Если кластер не последний, то элемент таблицы содержит номер следующего кластера. Содержимое следующего кластера должно быть прочитано вслед за первым. Когда будет найден последний кластер в цепочке, то, если файл не занимает весь кластер целиком, необходимо отсечь лишние байты кластера. Лишние байты отсекаются по длине файла, хранящейся в записи папки.
Чтобы записать файл, операционная система должна выполнить следующую последовательность действий. В свободном элементе папки создается описание файла, затем ищется свободный элемент FAT, и ссылка на него размещается в записи папки. Занимается первый кластер, описываемый найденным элементом FAT. В этот элемент FAT помещается номер следующего кластера или признак последнего кластера в цепочке.
Операционная система действует таким образом, чтобы собирать цепочки из соседних кластеров по нарастанию номера. Понятно, что обращение к последовательно расположенным кластерам будет происходить значительно быстрее, чем к кластерам, случайным образом разбросанным по диску. При этом игнорируются уже занятые и помеченные в FAT как дефектные кластеры.
В файловой системе FAT16 под номер кластера отведено 16 разрядов. Поэтому максимальное количество кластеров составляет 65525, а максимальный размер кластера 128 секторов. В таком случае максимальный размер разделов или дисков в FAT16 составляет 4,2 гигабайта. При логическом форматировании диска или раздела операционная система старается использовать минимальный размер кластера, при котором получающееся количество кластеров не превышает 65525. Очевидно, что чем больше размер раздела, тем больше должен быть размер кластера. Многие операционные системы неправильно работают с кластером размером в 128 секторов. В результате максимальный размер раздела FAT16 уменьшается до 2 гигабайт. Обычно чем больше размер кластера, тем больше становятся потери дискового пространства. Это связано с тем, что последний кластер, занимаемый файлом, заполнен лишь частично. Например, если файл размером 17 Кбайт записывается в раздел с размером кластера 16 Кбайт, то этот файл займет два кластера, причем первый кластер будет заполнен полностью, а во втором кластере будет записан только 1 Кбайт данных, а остальные 15 Кбайт пространства второго кластера останутся не заполненными и будут недоступными для записи других файлов. Если на больших дисках записывается большое количество маленьких файлов, то потери дискового пространства будут значительны. В следующей таблице приводятся сведения о возможных потерях дискового пространства при разных размерах раздела.
Размер раздела |
Размер кластера |
Потери дискового пространства |
|
127 Мб |
2 Кб |
2% |
|
128-255 Мб |
4 Кб |
4% |
|
256-511 МБ |
8 Кб |
10% |
|
512-1023 МБ |
16 Кб |
25% |
|
1024-2047 МБ |
32 Кб |
40% |
|
2048-4096 Мб |
64 Кб |
50% |
Возможны два способа уменьшения потерь дискового пространства.
Первый - разбиение дискового пространства на мелкие разделы с малым размером кластера. Второй - использование иной файловой системы, в которой для нумерации кластеров используется другое количество разрядов, что позволяет значительно уменьшить размер кластера.
Из всего выше сказанного следует, что основными недостатками файловой системы FAT16 являются:
· Невозможность поддержки разделов диска размером больше 2 Гб;
· Невозможность работы с файлами размером более 2 Гб;
· Невозможность работы с жесткими дисками емкостью более 8 Гб;
· Ограниченный размер корневой папки, которая может содержать не более 512 элементов.
Дисковый раздел FAT
Корневой каталог расположен на диске и имеет фиксированный размер. Каталоги -- специальные файлы с 32-битными элементами для каждого файла, содержащегося в этом каталоге. Элемент для каждого файла включает:
* имя файла (8+3 символа);
* байт атрибута (8 бит);
* время модификации (1б бит);
* дату модификации (16 бит);
* первый размещаемый блок (16 бит);
* размер файла (32 бита).
Эта информация используется всеми операционными системами, поддерживающими файловую систему FAT. Windows NT может сохранять и дополнительные отметки времени на элементе каталога FAT. Эти элементы позволяют определить момент последнего доступа к файлу и используются в основном приложениями POSIX.
Биты байта атрибута файла в элементе каталога указывают, имеет ли файл соответствующие атрибуты. Установленный первый бит идентифицирует файл как подкаталог; а второй -- в качестве метки тома. Обычно назначениями этих битов управляет операционная система. Кроме того, файлы FAT имеют четыре специальных атрибута, которые указывают, как эти файлы может применять пользователь. Различаются файлы архивный, системный, скрытый и только для чтения.
Windows NT использует биты атрибута для поддержки длинных (до 255 символов) имен файлов в разделах FAT. Применяемый для этого способ не мешает MS-DOS или OS/2 обращаться к подобному разделу. Всякий раз, когда пользователь создает файл с длинным (превышающим стандартное для FAT ограничение «8+3») именем, Windows NT учреждает элемент каталога для этого файла, соответствующий соглашению «8+3» (по тем правилам, что и для NTFS) с добавлением одного или нескольких вторичных элементов каталога. Каждый из таких вторичных элементов рассчитан на 13 символов в длинном имени файла и сохраняет длинную часть имени файла в UNICODE. Для этих элементов устанавливаются атрибуты: том, системный, скрытый, только для чтения. MS-DOS и OS/2 игнорируют элементы каталога с таким набором атрибутов, и последние не видимы в этих операционных системах. Вместо них MS-DOS и OS/2 обращаются к элементам, содержащим информацию в стандартном виде «8+3».
Некоторые дисковые утилиты сторонних производителей, взаимодействуя непосредственно с FAT, могут расценивать созданные Windows NT элементы каталога с длинным именем файла как ошибки логической структуры тома. Попытки этих утилит исправить ошибки могут привести к потере файлов и каталогов. Чтобы избежать подобных неприятностей, не используйте не проверенные на совместимость с Windows NT утилиты работы с диском или его дефрагментации.
Файловая система Windows NT FAT функционирует аналогично MS-DOS и Windows. Windows NT можно устанавливать на существующем разделе FAT. Если же компьютер работает под управлением Windows 95, длинные имена файлов и каталогов вполне допустимы, так как механизмы работы с длинными именами в обеих системах одинаковы.
Нельзя использовать Windows NT совместно с любыми программами сжатия или разбиения диска на разделы, если программное обеспечение требует драйверов MS-DOS. Для чтения подобных дисков нужны драйверы Windows NT.
Файловая система FAT является системой с точной записью, то есть при необходимости изменения структуры тома дается команда записи на диск. Недостаток такой системы -- медленное выполнение последовательных операций записи: ведь первая запись на диск должна быть завершена прежде, чем начнется вторая и т. д. Это не самое эффективное использование мощных компьютеров.
Допускается безболезненный перенос или копирование файлов с тома FAT на NTFS. При выполнении обратной операции информация о разрешениях и альтернативных потоках будет потеряна.
Внимание! Файловая система FAT не обеспечивает защиты данных и их автоматического восстановления. Поэтому FAT используется лишь в том случае, если на компьютере в качестве альтернативной системы установлена MS-DOS или Windows 95, а также для передачи данных на гибких дисках. Небольшой загрузочный раздел, отформатированный под FAT, требуется, кроме того, для RISC-систем. В остальных случаях использование FAT не рекомендуется.
Структура FAT
Общая информация
FAT состоит из 5 областей. Они перечислены в следующей таблице. Также в таблице указаны формулы для расчёта начала каждой области.
Название Адрес сектора (смещение)
Главная загрузочная запись MBR (Master Boot Record) = 0
Загрузочная запись раздела PBR (Partition Boot Record) = 1C8h (4 байта) в главной загрузочной записи
Записи FAT = загрузочная запись раздела + 0Eh (2 байта) в загрузочной записи раздела
Записи каталога = записи FAT + (16h (2 байта) * 10h (1 байт)) в загрузочной записи раздела
Область данных (кластер 0) = записи каталога + (11h (2 байта)*32/512) в загрузочной записи раздела
Размер сектора всегда составляет 512 байтов. Это число также указано в позиции загрузочной записи раздела 0Bh (размер записи 2 байта) в байтах.
Кластер образуется из нескольких объединённых секторов. Чтобы узнать, сколько секторов содержится в кластере, смотрите следующую таблицу.
Объем носителя данных |
Величина кластера FAT16 |
Величина кластера FAT32 |
Величина кластера NTFS |
|
7 Мб - 16 Мб |
2 Кб |
не поддерживается |
512 байтов |
|
17 Мб - 32 Мб |
512 байтов |
не поддерживается |
512 байтов |
|
33 Мб - 64 Мб |
1 Кб |
512 байтов |
512 байтов |
|
65 Мб - 128 Мб |
2 Кб |
1 Кб |
512 байтов |
|
129 Мб - 256 Мб |
4 Кб |
2 Кб |
512 байтов |
|
257 Мб - 512 Мб |
8 Кб |
4 Кб |
512 байтов |
|
513 Мб - 1 Гб |
16 Кб |
4 Кб |
1 Кб |
Количество секторов в кластере также указаны в позиции загрузочной записи раздела 0Dh (размер записи 1 байт).
Главная загрузочная запись (MBR)
Она содержит сведения о жёстком диске и его разделах.
Адрес |
Описание |
Размер, байтов |
|
000h |
Главная загрузочная запись |
446 |
|
1BEh |
1. Запись раздела |
16 |
|
1CEh |
2. Запись раздела |
16 |
|
1DEh |
3. Запись раздела |
16 |
|
1EEh |
4. Запись раздела |
16 |
|
1FEh |
Сигнатура BIOS (55h AAh) |
2 |
Первая запись раздела содержит следующие сведения:
Адрес |
Описание |
Размер поля, байтов |
|
00h |
Статус раздела: 0 если неактивный, 80h если активный. |
1 |
|
01h |
Головка, на которой начинается раздел |
1 |
|
02h |
Дорожка, на которой начинается раздел (биты 16-6), и сектор, на котором начинается раздел (биты 5-0). |
2 |
|
04h |
Тип раздела (1h - FAT12, 4h - FAT16<32Мб, 6h - FAT16>32Мб, Bh - FAT32) |
1 |
|
05h |
Головка, на которой заканчивается раздел. |
1 |
|
06h |
Дорожка, на которой заканчивается раздел (биты 16-6), и сектор, на котором заканчивается раздел (биты 5-0). |
2 |
|
08h |
Расстояние между сектором MBR и первым сектором раздела, в секторах |
4 |
|
0Ch |
Общее число секторов в разделе |
4 |
Загрузочная запись раздела (PBR)
Находится в разделе и содержит сведения о форматировании этого раздела.
Адрес |
Описание |
Размер поля, байтов |
|
00h |
Указание перехода + NOP |
3 |
|
03h |
OEM название |
8 |
|
0Bh |
Количество байтов в секторе на жестком диске |
2 |
|
0Dh |
Количество секторов в кластере |
1 |
|
0Eh |
Количество зарезервированных секторов |
2 |
|
10h |
Количество копий FAT, как правило, 2 |
1 |
|
11h |
Количество возможных записей в корневом каталоге: 512 при FAT16 |
2 |
|
13h |
Количество секторов в более маленьких разделах |
2 |
|
15h |
Тип носителя: F8 для жестких дисков; F0 для дискет. |
1 |
|
16h |
Секторов на FAT |
2 |
|
18h |
Секторов на дорожку |
2 |
|
1Ah |
Число головок |
2 |
|
1Ch |
Зарезервированные сектора в начале жесткого диска |
4 |
|
20h |
Общее число секторов в разделе |
4 |
|
24h |
Номер дисковода. Первый жёсткий диск имеет обозначение 80h, второй 81h и т.д. |
2 |
|
26h |
Расширенная загрузочная сигнатура (29h) |
1 |
|
27h |
Серийный номер носителя данных |
4 |
|
2Bh |
Наименование носителя данных |
11 |
|
36h |
Название FAT (FAT16) |
8 |
|
3Eh |
Исполняемый код |
448 |
|
1FEh |
Сигнатура (55h AAh) |
2 |
Записи FAT
Каждая запись имеет размер 2 байта, а её позиция соответствует кластеру в области данных.
Запись содержит в себе либо номер следующего кластера файла, либо состояние текущего кластера.
Рис. 1. Записи FAT
Обозначения:
0000 |
Неиспользуемый кластер |
|
от 1 до количества кластеров |
Номер кластера со следующей частью файла |
|
FFFF0h - FFFF6 |
Зарезервированный кластер |
|
FFF7 |
Испорченный кластер |
|
FFF8h - FFFFh |
Конец файла (эта позиция соответствует последнему кластеру файла ) |
В данном примере файл "HaloWelt.txt" начинается в кластере 05h. В FAT-таблице на позиции 05h стоит значение FFFFh, то есть файл "HaloWelt.txt" не нуждается в следующем кластере. В области данных в кластере 5h должен находиться текст файла.
Файл "Format.exe" начинается в кластере 6h и занимает 3 последовательных кластера.
Файл "Zerstuke.exe" начинается в кластере Ch и занимает 3 кластера в различных местах носителя данных.
Кластер 9h отмечен как "испорченный".
Первые 2 позиции в FAT зарезервированы, но в области данных данные начинаются с кластера 0. Поэтому кластер в области данных = (номер кластера в FAT) - 2.
На приведённой выше иллюстрации это не учтено для упрощения понимания структуры.
Записи каталога
Адрес |
Размер, байтов |
Значение |
|
0h |
8 |
Имя файла |
|
8h |
3 |
Расширение |
|
0Bh |
1 |
Свойства файла (00ARSHDV)00: зарезервированные битыA: бит "архивный"R: бит "только для чтения"S: бит "системный"D: бит "каталог"V: бит "том" |
|
16h |
2 |
Время |
|
18h |
2 |
Дата |
|
1Ah |
2 |
Первый кластер |
|
1Ch |
4 |
Размер |
Область данных (кластер 0)
Данные файла начинаются в соответствующем кластере без предварительного предупреждения. Если последний кластер не полон, оставшиеся байты имеют значение 00h. Таким образом, если файл содержит только 1 байт, этот файл займёт 1 Кбайт памяти (если размер кластера равен двум секторам). Оставшиеся 1023 байта кластера будут содержать нули. Чтобы найти последний байт файла, нужно взять величину файла из позиции записи каталога 1Ch (4 байт) и вычесть из него значение (количество кластеров файла - 1)*размер кластера.
Для жёсткого диска:
Главная загрузочная запись создаётся с помощью fdisk.exe.
Загрузочная запись тома создаётся с помощью format.exe.
При дефрагментации данных кластеры файла присоединяются последовательно друг к другу (если это конечно возможно).
Scandisk.exe сравнивает копии таблиц FAT и проверяет, совпадает ли размер файла с количеством кластеров. Кластер также не может принадлежать двум файлам или два раза появляться в файле.
Приложение 1 (исходный код UNIX для FAT16)
/* $FreeBSD: src/sys/fs/msdosfs/msdosfs_fat.c,v 1.56 2011/11/22 13:30:36 kib Exp $ */
/* $NetBSD: msdosfs_fat.c,v 1.28 1997/11/17 15:36:49 ws Exp $ */
/*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
* Copyright (C) 1994, 1995, 1997 TooLs GmbH.
* All rights reserved.
* Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
* You can do anything you want with this software, just don't say you wrote
* it, and don't remove this notice.
*
* This software is provided "as is".
*
* The author supplies this software to be publicly redistributed on the
* understanding that the author is not responsible for the correct
* functioning of this software in any circumstances and is not liable for
* any damages caused by this software.
*
* October 1992
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/direntry.h>
#include <fs/msdosfs/denode.h>
#include <fs/msdosfs/fat.h>
#include <fs/msdosfs/msdosfsmount.h>
static int chainalloc(struct msdosfsmount *pmp, u_long start,
u_long count, u_long fillwith, u_long *retcluster,
u_long *got);
static int chainlength(struct msdosfsmount *pmp, u_long start,
u_long count);
static void fatblock(struct msdosfsmount *pmp, u_long ofs, u_long *bnp,
u_long *sizep, u_long *bop);
static int fatchain(struct msdosfsmount *pmp, u_long start, u_long count,
u_long fillwith);
static void fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp,
u_long *fsrcnp);
static void updatefats(struct msdosfsmount *pmp, struct buf *bp,
u_long fatbn);
static __inline void
usemap_alloc(struct msdosfsmount *pmp, u_long cn);
static __inline void
usemap_free(struct msdosfsmount *pmp, u_long cn);
static int clusteralloc1(struct msdosfsmount *pmp, u_long start,
u_long count, u_long fillwith, u_long *retcluster,
u_long *got);
static void
fatblock(pmp, ofs, bnp, sizep, bop)
struct msdosfsmount *pmp;
u_long ofs;
u_long *bnp;
u_long *sizep;
u_long *bop;
{
u_long bn, size;
bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
* DEV_BSIZE;
bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
if (bnp)
*bnp = bn;
if (sizep)
*sizep = size;
if (bop)
*bop = ofs % pmp->pm_fatblocksize;
}
/*
* Map the logical cluster number of a file into a physical disk sector
* that is filesystem relative.
*
* dep - address of denode representing the file of interest
* findcn - file relative cluster whose filesystem relative cluster number
* and/or block number are/is to be found
* bnp - address of where to place the filesystem relative block number.
* If this pointer is null then don't return this quantity.
* cnp - address of where to place the filesystem relative cluster number.
* If this pointer is null then don't return this quantity.
*
* NOTE: Either bnp or cnp must be non-null.
* This function has one side effect. If the requested file relative cluster
* is beyond the end of file, then the actual number of clusters in the file
* is returned in *cnp. This is useful for determining how long a directory is.
* If cnp is null, nothing is returned.
*/
int
pcbmap(dep, findcn, bnp, cnp, sp)
struct denode *dep;
u_long findcn; /* file relative cluster to get */
daddr_t *bnp; /* returned filesys relative blk number */
u_long *cnp; /* returned cluster number */
int *sp; /* returned block size */
{
int error;
u_long i;
u_long cn;
u_long prevcn = 0; /* XXX: prevcn could be used unititialized */
u_long byteoffset;
u_long bn;
u_long bo;
struct buf *bp = NULL;
u_long bp_bn = -1;
struct msdosfsmount *pmp = dep->de_pmp;
u_long bsize;
KASSERT(bnp != NULL || cnp != NULL || sp != NULL,
("pcbmap: extra call"));
ASSERT_VOP_ELOCKED(DETOV(dep), "pcbmap");
cn = dep->de_StartCluster;
/*
* The "file" that makes up the root directory is contiguous,
* permanently allocated, of fixed size, and is not made up of
* clusters. If the cluster number is beyond the end of the root
* directory, then return the number of clusters in the file.
*/
if (cn == MSDOSFSROOT) {
if (dep->de_Attributes & ATTR_DIRECTORY) {
if (de_cn2off(pmp, findcn) >= dep->de_FileSize) {
if (cnp)
*cnp = de_bn2cn(pmp, pmp->pm_rootdirsize);
return (E2BIG);
}
if (bnp)
*bnp = pmp->pm_rootdirblk + de_cn2bn(pmp, findcn);
if (cnp)
*cnp = MSDOSFSROOT;
if (sp)
*sp = min(pmp->pm_bpcluster,
dep->de_FileSize - de_cn2off(pmp, findcn));
return (0);
} else { /* just an empty file */
if (cnp)
*cnp = 0;
return (E2BIG);
}
}
/*
* All other files do I/O in cluster sized blocks
*/
if (sp)
*sp = pmp->pm_bpcluster;
/*
* Rummage around in the fat cache, maybe we can avoid tromping
* thru every fat entry for the file. And, keep track of how far
* off the cache was from where we wanted to be.
*/
i = 0;
fc_lookup(dep, findcn, &i, &cn);
/*
* Handle all other files or directories the normal way.
*/
for (; i < findcn; i++) {
/*
* Stop with all reserved clusters, not just with EOF.
*/
if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
goto hiteof;
byteoffset = FATOFS(pmp, cn);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
if (bn != bp_bn) {
if (bp)
brelse(bp);
error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bp_bn = bn;
}
prevcn = cn;
if (bo >= bsize) {
if (bp)
brelse(bp);
return (EIO);
}
if (FAT32(pmp))
cn = getulong(&bp->b_data[bo]);
else
cn = getushort(&bp->b_data[bo]);
if (FAT12(pmp) && (prevcn & 1))
cn >>= 4;
cn &= pmp->pm_fatmask;
/*
* Force the special cluster numbers
* to be the same for all cluster sizes
* to let the rest of msdosfs handle
* all cases the same.
*/
if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
cn |= ~pmp->pm_fatmask;
}
if (!MSDOSFSEOF(pmp, cn)) {
if (bp)
brelse(bp);
if (bnp)
*bnp = cntobn(pmp, cn);
if (cnp)
*cnp = cn;
fc_setcache(dep, FC_LASTMAP, i, cn);
return (0);
}
hiteof:;
if (cnp)
*cnp = i;
if (bp)
brelse(bp);
/* update last file cluster entry in the fat cache */
fc_setcache(dep, FC_LASTFC, i - 1, prevcn);
return (E2BIG);
}
/*
* Find the closest entry in the fat cache to the cluster we are looking
* for.
*/
static void
fc_lookup(dep, findcn, frcnp, fsrcnp)
struct denode *dep;
u_long findcn;
u_long *frcnp;
u_long *fsrcnp;
{
int i;
u_long cn;
struct fatcache *closest = 0;
ASSERT_VOP_LOCKED(DETOV(dep), "fc_lookup");
for (i = 0; i < FC_SIZE; i++) {
cn = dep->de_fc[i].fc_frcn;
if (cn != FCE_EMPTY && cn <= findcn) {
if (closest == 0 || cn > closest->fc_frcn)
closest = &dep->de_fc[i];
}
}
if (closest) {
*frcnp = closest->fc_frcn;
*fsrcnp = closest->fc_fsrcn;
}
}
/*
* Purge the fat cache in denode dep of all entries relating to file
* relative cluster frcn and beyond.
*/
void
fc_purge(dep, frcn)
struct denode *dep;
u_int frcn;
{
int i;
struct fatcache *fcp;
ASSERT_VOP_ELOCKED(DETOV(dep), "fc_purge");
fcp = dep->de_fc;
for (i = 0; i < FC_SIZE; i++, fcp++) {
if (fcp->fc_frcn >= frcn)
fcp->fc_frcn = FCE_EMPTY;
}
}
файл операционный система кластер
/*
* Update the fat.
* If mirroring the fat, update all copies, with the first copy as last.
* Else update only the current fat (ignoring the others).
*
* pmp - msdosfsmount structure for filesystem to update
* bp - addr of modified fat block
* fatbn - block number relative to begin of filesystem of the modified fat block.
*/
static void
updatefats(pmp, bp, fatbn)
struct msdosfsmount *pmp;
struct buf *bp;
u_long fatbn;
{
int i;
struct buf *bpn;
#ifdef MSDOSFS_DEBUG
printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
#endif
/*
* If we have an FSInfo block, update it.
*/
if (pmp->pm_fsinfo) {
if (bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
NOCRED, &bpn) != 0) {
/*
* Ignore the error, but turn off FSInfo update for the future.
*/
pmp->pm_fsinfo = 0;
brelse(bpn);
} else {
struct fsinfo *fp = (struct fsinfo *)bpn->b_data;
putulong(fp->fsinfree, pmp->pm_freeclustercount);
putulong(fp->fsinxtfree, pmp->pm_nxtfree);
if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
bwrite(bpn);
else
bdwrite(bpn);
}
}
if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
/*
* Now copy the block(s) of the modified fat to the other copies of
* the fat and write them out. This is faster than reading in the
* other fats and then writing them back out. This could tie up
* the fat for quite a while. Preventing others from accessing it.
* To prevent us from going after the fat quite so much we use
* delayed writes, unless they specfied "synchronous" when the
* filesystem was mounted. If synch is asked for then use
* bwrite()'s and really slow things down.
*/
for (i = 1; i < pmp->pm_FATs; i++) {
fatbn += pmp->pm_FATsecs;
/* getblk() never fails */
bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount,
0, 0, 0);
bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
bwrite(bpn);
else
bdwrite(bpn);
}
}
/*
* Write out the first (or current) fat last.
*/
if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
bwrite(bp);
else
bdwrite(bp);
/*
* Maybe update fsinfo sector here?
*/
}
/*
* Updating entries in 12 bit fats is a pain in the butt.
*
* The following picture shows where nibbles go when moving from a 12 bit
* cluster number into the appropriate bytes in the FAT.
*
* byte m byte m+1 byte m+2
* +----+----+ +----+----+ +----+----+
* | 0 1 | | 2 3 | | 4 5 | FAT bytes
* +----+----+ +----+----+ +----+----+
*
* +----+----+----+ +----+----+----+
* | 3 0 1 | | 4 5 2 |
* +----+----+----+ +----+----+----+
* cluster n cluster n+1
*
* Where n is even. m = n + (n >> 2)
*
*/
static __inline void
usemap_alloc(pmp, cn)
struct msdosfsmount *pmp;
u_long cn;
{
MSDOSFS_ASSERT_MP_LOCKED(pmp);
KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
== 0, ("Allocating used sector %ld %ld %x", cn, cn % N_INUSEBITS,
(unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
KASSERT(pmp->pm_freeclustercount > 0, ("usemap_alloc: too little"));
pmp->pm_freeclustercount--;
}
static __inline void
usemap_free(pmp, cn)
struct msdosfsmount *pmp;
u_long cn;
{
MSDOSFS_ASSERT_MP_LOCKED(pmp);
pmp->pm_freeclustercount++;
KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
!= 0, ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS,
(unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
}
int
clusterfree(pmp, cluster, oldcnp)
struct msdosfsmount *pmp;
u_long cluster;
u_long *oldcnp;
{
int error;
u_long oldcn;
error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE);
if (error)
return (error);
/*
* If the cluster was successfully marked free, then update
* the count of free clusters, and turn off the "allocated"
* bit in the "in use" cluster bit map.
*/
MSDOSFS_LOCK_MP(pmp);
usemap_free(pmp, cluster);
MSDOSFS_UNLOCK_MP(pmp);
if (oldcnp)
*oldcnp = oldcn;
return (0);
}
/*
* Get or Set or 'Get and Set' the cluster'th entry in the fat.
*
* function - whether to get or set a fat entry
* pmp - address of the msdosfsmount structure for the filesystem
* whose fat is to be manipulated.
* cn - which cluster is of interest
* oldcontents - address of a word that is to receive the contents of the
* cluster'th entry if this is a get function
* newcontents - the new value to be written into the cluster'th element of
* the fat if this is a set function.
*
* This function can also be used to free a cluster by setting the fat entry
* for a cluster to 0.
*
* All copies of the fat are updated if this is a set function. NOTE: If
* fatentry() marks a cluster as free it does not update the inusemap in
* the msdosfsmount structure. This is left to the caller.
*/
int
fatentry(function, pmp, cn, oldcontents, newcontents)
int function;
struct msdosfsmount *pmp;
u_long cn;
u_long *oldcontents;
u_long newcontents;
{
int error;
u_long readcn;
u_long bn, bo, bsize, byteoffset;
struct buf *bp;
#ifdef MSDOSFS_DEBUG
printf("fatentry(func %d, pmp %p, clust %lu, oldcon %p, newcon %lx)\n",
function, pmp, cn, oldcontents, newcontents);
#endif
#ifdef DIAGNOSTIC
/*
* Be sure they asked us to do something.
*/
if ((function & (FAT_SET | FAT_GET)) == 0) {
#ifdef MSDOSFS_DEBUG
printf("fatentry(): function code doesn't specify get or set\n");
#endif
return (EINVAL);
}
/*
* If they asked us to return a cluster number but didn't tell us
* where to put it, give them an error.
*/
if ((function & FAT_GET) && oldcontents == NULL) {
#ifdef MSDOSFS_DEBUG
printf("fatentry(): get function with no place to put result\n");
#endif
return (EINVAL);
}
#endif
/*
* Be sure the requested cluster is in the filesystem.
*/
if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster)
return (EINVAL);
byteoffset = FATOFS(pmp, cn);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
if (function & FAT_GET) {
if (FAT32(pmp))
readcn = getulong(&bp->b_data[bo]);
else
readcn = getushort(&bp->b_data[bo]);
if (FAT12(pmp) & (cn & 1))
readcn >>= 4;
readcn &= pmp->pm_fatmask;
/* map reserved fat entries to same values for all fats */
if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
readcn |= ~pmp->pm_fatmask;
*oldcontents = readcn;
}
if (function & FAT_SET) {
switch (pmp->pm_fatmask) {
case FAT12_MASK:
readcn = getushort(&bp->b_data[bo]);
if (cn & 1) {
readcn &= 0x000f;
readcn |= newcontents << 4;
} else {
readcn &= 0xf000;
readcn |= newcontents & 0xfff;
}
putushort(&bp->b_data[bo], readcn);
break;
case FAT16_MASK:
putushort(&bp->b_data[bo], newcontents);
break;
case FAT32_MASK:
/*
* According to spec we have to retain the
* high order bits of the fat entry.
*/
readcn = getulong(&bp->b_data[bo]);
readcn &= ~FAT32_MASK;
readcn |= newcontents & FAT32_MASK;
putulong(&bp->b_data[bo], readcn);
break;
}
updatefats(pmp, bp, bn);
bp = NULL;
pmp->pm_fmod = 1;
}
if (bp)
brelse(bp);
return (0);
}
/*
* Update a contiguous cluster chain
*
* pmp - mount point
* start - first cluster of chain
* count - number of clusters in chain
* fillwith - what to write into fat entry of last cluster
*/
static int
fatchain(pmp, start, count, fillwith)
struct msdosfsmount *pmp;
u_long start;
u_long count;
u_long fillwith;
{
int error;
u_long bn, bo, bsize, byteoffset, readcn, newc;
struct buf *bp;
#ifdef MSDOSFS_DEBUG
printf("fatchain(pmp %p, start %lu, count %lu, fillwith %lx)\n",
pmp, start, count, fillwith);
#endif
/*
* Be sure the clusters are in the filesystem.
*/
if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster)
return (EINVAL);
while (count > 0) {
byteoffset = FATOFS(pmp, start);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
while (count > 0) {
start++;
newc = --count > 0 ? start : fillwith;
switch (pmp->pm_fatmask) {
case FAT12_MASK:
readcn = getushort(&bp->b_data[bo]);
if (start & 1) {
readcn &= 0xf000;
readcn |= newc & 0xfff;
} else {
readcn &= 0x000f;
readcn |= newc << 4;
}
putushort(&bp->b_data[bo], readcn);
bo++;
if (!(start & 1))
bo++;
break;
case FAT16_MASK:
putushort(&bp->b_data[bo], newc);
bo += 2;
break;
case FAT32_MASK:
readcn = getulong(&bp->b_data[bo]);
readcn &= ~pmp->pm_fatmask;
readcn |= newc & pmp->pm_fatmask;
putulong(&bp->b_data[bo], readcn);
bo += 4;
break;
}
if (bo >= bsize)
break;
}
updatefats(pmp, bp, bn);
}
pmp->pm_fmod = 1;
return (0);
}
/*
* Check the length of a free cluster chain starting at start.
*
* pmp - mount point
* start - start of chain
* count - maximum interesting length
*/
static int
chainlength(pmp, start, count)
struct msdosfsmount *pmp;
u_long start;
u_long count;
{
u_long idx, max_idx;
u_int map;
u_long len;
MSDOSFS_ASSERT_MP_LOCKED(pmp);
max_idx = pmp->pm_maxcluster / N_INUSEBITS;
idx = start / N_INUSEBITS;
start %= N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map &= ~((1 << start) - 1);
if (map) {
len = ffs(map) - 1 - start;
return (len > count ? count : len);
}
len = N_INUSEBITS - start;
if (len >= count)
return (count);
while (++idx <= max_idx) {
if (len >= count)
break;
map = pmp->pm_inusemap[idx];
if (map) {
len += ffs(map) - 1;
break;
}
len += N_INUSEBITS;
}
return (len > count ? count : len);
}
/*
* Allocate contigous free clusters.
*
* pmp - mount point.
* start - start of cluster chain.
* count - number of clusters to allocate.
* fillwith - put this value into the fat entry for the
* last allocated cluster.
* retcluster - put the first allocated cluster's number here.
* got - how many clusters were actually allocated.
*/
static int
chainalloc(pmp, start, count, fillwith, retcluster, got)
struct msdosfsmount *pmp;
u_long start;
u_long count;
u_long fillwith;
u_long *retcluster;
u_long *got;
{
int error;
u_long cl, n;
MSDOSFS_ASSERT_MP_LOCKED(pmp);
for (cl = start, n = count; n-- > 0;)
usemap_alloc(pmp, cl++);
error = fatchain(pmp, start, count, fillwith);
if (error != 0)
return (error);
#ifdef MSDOSFS_DEBUG
printf("clusteralloc(): allocated cluster chain at %lu (%lu clusters)\n",
start, count);
#endif
if (retcluster)
*retcluster = start;
if (got)
*got = count;
pmp->pm_nxtfree = start + count;
if (pmp->pm_nxtfree > pmp->pm_maxcluster)
pmp->pm_nxtfree = CLUST_FIRST;
return (0);
}
/*
* Allocate contiguous free clusters.
*
* pmp - mount point.
* start - preferred start of cluster chain.
* count - number of clusters requested.
* fillwith - put this value into the fat entry for the
* last allocated cluster.
* retcluster - put the first allocated cluster's number here.
* got - how many clusters were actually allocated.
*/
int
clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count,
u_long fillwith, u_long *retcluster, u_long *got)
{
int error;
MSDOSFS_LOCK_MP(pmp);
error = clusteralloc1(pmp, start, count, fillwith, retcluster, got);
MSDOSFS_UNLOCK_MP(pmp);
return (error);
}
static int
clusteralloc1(struct msdosfsmount *pmp, u_long start, u_long count,
u_long fillwith, u_long *retcluster, u_long *got)
{
u_long idx;
u_long len, newst, foundl, cn, l;
u_long foundcn = 0; /* XXX: foundcn could be used unititialized */
u_int map;
MSDOSFS_ASSERT_MP_LOCKED(pmp);
#ifdef MSDOSFS_DEBUG
printf("clusteralloc(): find %lu clusters\n", count);
#endif
if (start) {
if ((len = chainlength(pmp, start, count)) >= count)
return (chainalloc(pmp, start, count, fillwith, retcluster, got));
} else
len = 0;
newst = pmp->pm_nxtfree;
foundl = 0;
for (cn = newst; cn <= pmp->pm_maxcluster;) {
idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1;
if (map != (u_int)-1) {
cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
if ((l = chainlength(pmp, cn, count)) >= count)
return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
if (l > foundl) {
foundcn = cn;
foundl = l;
}
cn += l + 1;
continue;
}
cn += N_INUSEBITS - cn % N_INUSEBITS;
}
for (cn = 0; cn < newst;) {
idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1;
if (map != (u_int)-1) {
cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
if ((l = chainlength(pmp, cn, count)) >= count)
return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
if (l > foundl) {
foundcn = cn;
foundl = l;
}
cn += l + 1;
continue;
}
cn += N_INUSEBITS - cn % N_INUSEBITS;
}
if (!foundl)
return (ENOSPC);
if (len)
return (chainalloc(pmp, start, len, fillwith, retcluster, got));
else
return (chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got));
}
/*
* Free a chain of clusters.
*
* pmp - address of the msdosfs mount structure for the filesystem
* containing the cluster chain to be freed.
* startcluster - number of the 1st cluster in the chain of clusters to be
* freed.
*/
int
freeclusterchain(pmp, cluster)
struct msdosfsmount *pmp;
u_long cluster;
{
int error;
struct buf *bp = NULL;
u_long bn, bo, bsize, byteoffset;
u_long readcn, lbn = -1;
MSDOSFS_LOCK_MP(pmp);
while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
byteoffset = FATOFS(pmp, cluster);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
if (lbn != bn) {
if (bp)
updatefats(pmp, bp, lbn);
error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
if (error) {
brelse(bp);
MSDOSFS_UNLOCK_MP(pmp);
return (error);
}
lbn = bn;
}
usemap_free(pmp, cluster);
switch (pmp->pm_fatmask) {
case FAT12_MASK:
readcn = getushort(&bp->b_data[bo]);
if (cluster & 1) {
cluster = readcn >> 4;
readcn &= 0x000f;
readcn |= MSDOSFSFREE << 4;
} else {
cluster = readcn;
readcn &= 0xf000;
readcn |= MSDOSFSFREE & 0xfff;
}
putushort(&bp->b_data[bo], readcn);
break;
case FAT16_MASK:
cluster = getushort(&bp->b_data[bo]);
putushort(&bp->b_data[bo], MSDOSFSFREE);
break;
case FAT32_MASK:
cluster = getulong(&bp->b_data[bo]);
putulong(&bp->b_data[bo],
(MSDOSFSFREE & FAT32_MASK) | (cluster & ~FAT32_MASK));
break;
}
cluster &= pmp->pm_fatmask;
if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD)
cluster |= pmp->pm_fatmask;
}
if (bp)
updatefats(pmp, bp, bn);
MSDOSFS_UNLOCK_MP(pmp);
return (0);
}
/*
* Read in fat blocks looking for free clusters. For every free cluster
* found turn off its corresponding bit in the pm_inusemap.
*/
int
fillinusemap(pmp)
struct msdosfsmount *pmp;
{
struct buf *bp = NULL;
u_long cn, readcn;
int error;
u_long bn, bo, bsize, byteoffset;
MSDOSFS_ASSERT_MP_LOCKED(pmp);
/*
* Mark all clusters in use, we mark the free ones in the fat scan
* loop further down.
*/
for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++)
pmp->pm_inusemap[cn] = (u_int)-1;
/*
* Figure how many free clusters are in the filesystem by ripping
* through the fat counting the number of entries whose content is
* zero. These represent free clusters.
*/
pmp->pm_freeclustercount = 0;
for (cn = CLUST_FIRST; cn <= pmp->pm_maxcluster; cn++) {
byteoffset = FATOFS(pmp, cn);
bo = byteoffset % pmp->pm_fatblocksize;
if (!bo || !bp) {
/* Read new FAT block */
if (bp)
brelse(bp);
fatblock(pmp, byteoffset, &bn, &bsize, NULL);
error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
}
if (FAT32(pmp))
readcn = getulong(&bp->b_data[bo]);
else
readcn = getushort(&bp->b_data[bo]);
if (FAT12(pmp) && (cn & 1))
readcn >>= 4;
readcn &= pmp->pm_fatmask;
if (readcn == 0)
usemap_free(pmp, cn);
}
if (bp != NULL)
brelse(bp);
return (0);
}
/*
* Allocate a new cluster and chain it onto the end of the file.
*
* dep - the file to extend
* count - number of clusters to allocate
* bpp - where to return the address of the buf header for the first new
* file block
* ncp - where to put cluster number of the first newly allocated cluster
* If this pointer is 0, do not return the cluster number.
* flags - see fat.h
*
* NOTE: This function is not responsible for turning on the DE_UPDATE bit of
* the de_flag field of the denode and it does not change the de_FileSize
* field. This is left for the caller to do.
*/
int
extendfile(dep, count, bpp, ncp, flags)
struct denode *dep;
u_long count;
struct buf **bpp;
u_long *ncp;
int flags;
{
int error;
u_long frcn;
u_long cn, got;
struct msdosfsmount *pmp = dep->de_pmp;
struct buf *bp;
daddr_t blkno;
/*
* Don't try to extend the root directory
*/
if (dep->de_StartCluster == MSDOSFSROOT
&& (dep->de_Attributes & ATTR_DIRECTORY)) {
#ifdef MSDOSFS_DEBUG
printf("extendfile(): attempt to extend root directory\n");
#endif
return (ENOSPC);
}
/*
* If the "file's last cluster" cache entry is empty, and the file
* is not empty, then fill the cache entry by calling pcbmap().
*/
if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY &&
dep->de_StartCluster != 0) {
error = pcbmap(dep, 0xffff, 0, &cn, 0);
/* we expect it to return E2BIG */
if (error != E2BIG)
return (error);
}
dep->de_fc[FC_NEXTTOLASTFC].fc_frcn =
dep->de_fc[FC_LASTFC].fc_frcn;
dep->de_fc[FC_NEXTTOLASTFC].fc_fsrcn =
dep->de_fc[FC_LASTFC].fc_fsrcn;
while (count > 0) {
/*
* Allocate a new cluster chain and cat onto the end of the
* file. * If the file is empty we make de_StartCluster point
* to the new block. Note that de_StartCluster being 0 is
* sufficient to be sure the file is empty since we exclude
* attempts to extend the root directory above, and the root
* dir is the only file with a startcluster of 0 that has
* blocks allocated (sort of).
*/
if (dep->de_StartCluster == 0)
cn = 0;
else
cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1;
error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got);
if (error)
return (error);
count -= got;
/*
* Give them the filesystem relative cluster number if they want
* it.
*/
if (ncp) {
*ncp = cn;
ncp = NULL;
}
if (dep->de_StartCluster == 0) {
dep->de_StartCluster = cn;
frcn = 0;
} else {
error = fatentry(FAT_SET, pmp,
dep->de_fc[FC_LASTFC].fc_fsrcn,
0, cn);
if (error) {
clusterfree(pmp, cn, NULL);
return (error);
}
frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
}
/*
* Update the "last cluster of the file" entry in the denode's fat
Подобные документы
Работа с файлами, каталогами и томами в Windows и Win32 API. Функции GetWindowsDirectory и GetSystemDirectory. Примеры работы с томами. Получение и изменение атрибутов файлов. Описание минимального набора базовых функций Windows. Чтение и запись файлов.
лекция [62,7 K], добавлен 24.06.2009Появление операционной системы Windows 95. Правила присвоения имен файлам. Порядок хранения файлов на диске. Система хранения файлов и организации каталогов. Многоуровневая иерархическая файловая система. Полное имя файла. Иерархия папок Windows.
презентация [103,0 K], добавлен 11.03.2015Общее понятие термина "файл". Имя файла и его расширение. Типы и параметры файлов, их значение. Понятие "файловая система" и "файловая структура диска". Построение дерева каталогов. Особенности имени файла в операционной системе MS-DOS и Windows.
презентация [2,7 M], добавлен 18.10.2010История Windows. Особенности Windows XP. Файловая система и структура. Основные принципы работы с системой. Начало и завершение работы, главное меню. Запуск и завершение программ. Окна и диалоги, панель задач. Установка Windows XP.
курсовая работа [344,0 K], добавлен 24.04.2007Набор данных на диске, имеющий имя. Порядок размещения файлов. Многоуровневая файловая система. Полный адрес файла. Логические диски и файловые системы в Windows. Работа с файлами в Windows. Связь расширения с программой. Поиск компьютеров в сети.
презентация [1,9 M], добавлен 12.12.2012Распространенные файловые системы. Обзор файловой системы FAT. Имена файлов в FAT. Файловая система FAT 32. Файловая система HPFS: суперблок, запасной блок, преимущества и недостатки. Файловая система NTFS. Устранение ограничения. Сравнение систем.
реферат [31,5 K], добавлен 27.10.2007Семейство ОС Windows 2000. Windows 2000 Server. Windows 2000 Advanced Server. Windows 2000 Datacenter Server. ОС Windows Server 2003. Организация сети на основе Windows 2000. Службы каталогов, DHCP, DNS, WINS. Конфигурирование сервера.
курсовая работа [307,1 K], добавлен 06.10.2006История создания. Windows 9x/NT. Операционная система Microsoft Windows. Преимущества и недостатки Windows. Некоторые клавиатурные комбинации Windows 9x и NT. Windows XP Professional. Наиболее совершенная защита.
реферат [19,3 K], добавлен 18.07.2004Универсальная многоцелевая сетевая операционная система Windows NT Server. Использование Windows NT Workstation как невыделенного сервера в одноранговых сетях и в качестве клиента сетей. Операционные системы Windows 2003, Windows Vista и Windows 7.
презентация [6,2 K], добавлен 23.10.2013Особенности и принцип действия файловой системы NTFS - одной из самых сложных и удачных из существующих на данный момент файловых систем. Функции файловой системы NTFS: разреженные файлы, журнал изменений, компрессия файлов и каталогов, жесткие связи.
реферат [17,4 K], добавлен 24.12.2010