Как сделать файловую систему доступной для записи

Обновлено: 04.07.2024

В пятой части нашей серии статей мы показали, как можно использовать прерывания BIOS'а после перехода в защищенный режим, и в качестве примера определили размер оперативной памяти. Сегодня мы разовьем этот успех и реализуем полноценную поддержку работы с дисками с файловой системой FAT16 и FAT32. Работу с файлами на диске можно разбить на 2 части: работа с файловой системой и работа с диском на уровне чтения/записи секторов. Можно сказать, что для этого нам нужно написать «драйвер» файловой системы и «драйвер» диска.

Работа с диском на уровне чтения/записи секторов

Для начала научимся работать с диском.
Итак, мы можем вызывать прерывания BIOS'а. Помимо прочих возможностей, BIOS предоставляет интерфейс для работы с диском, а именно — прерывание int 0x13. Со списком сервисов, предоставляемых прерыванием, можно ознакомиться на википедии. Нас интересуют сервисы чтения и записи дисков.

Существует два способа адресации сектора на диске, с которыми работает BIOS – CHS(cylinder-head-sector) и LBA(logical block addressing). Адресация CHS основана на использовании геометрии диска, и адресом сектора является совокупность трех координат: цилиндр, головка, сектор. Способ позволяет адресовать до 8Гб. Прерывание int0x13 предоставляет возможность читать и писать на диск с использованием этой адресации.

Понятно, что 8Гб — это очень мало, и данный способ адресации является устаревшим, а все современные (и не очень) контроллеры жестких дисков поддерживают адресацию LBA. Адресация LBA абстрагируется от геометрии диска и присваивает каждому сектору собственный номер. Нумерация секторов начинается с нуля. LBA для задания номера блока использует 48 бит, что позволяет адресовать 128 ПиБ, с учетом размера сектора в 512 байт. Прерывание int0x13 предоставляет два сервиса для чтения и записи секторов на диск с использованием LBA. Их мы и будем использовать. Для чтения сектора прерывание in0x13 ожидает следующие параметры:



Прерывание возвращает следующие значения:


Один из параметров – номер диска. Нужно как-то узнать номер диска, с которым мы собрались работать. Нумерация происходит следующим образом: флоппи-диски (fdd), и все, что эмулируется как флоппи, нумеруются с нуля, а жесткие диски (hdd), и все, что эмулируется как они(usb-флешки, например), нумеруются с 0x80. Этот номер никак не связан с последовательностью загрузки в настройках BIOS’а. В нашем случае, диск, с которым мы собираемся работать, является тем диском, с которого мы загрузились.

Когда BIOS передает управление MBR, он загружает его по адресу 0000h:7C00h, а в регистре DL передает нужный нам номер загрузочного устройства. Это является частью интерфейса взаимодействия между BIOS и MBR. Таким образом, этот номер попадает в GRUB, где далее используется для работы с диском. GRUB, в свою очередь, передает этот номер ОС как часть структуры Multiboot information.

Сразу после передачи управления от GRUB’а к ОС в регистре EBX находится указатель на эту структуру. Первое поле структуры – это flags, и если в нем выставлен 2-й бит, то поле boot_device корректно. Это поле так же принадлежит структуре Multiboot information и в его старшем байте (размер поля – 4 байта) хранится нужный нам номер диска, который понимает прерывание int0x13. Таким образом, используя GRUB, мы получили недостающий параметр для чтения/записи секторов на диск.

Мы научились читать и писать сектора на диск, это, безусловно, важно. Но файловая система привязана не к целому диску, а только к его части – разделу. Для работы с файловой системой нужно найти сектор, с которого начинается раздел, на котором она располагается. Информация об имеющихся на диске секторах хранится в первом секторе диска, там же, где располагается MBR. Существует много различных форматов MBR, но для всех них верна следующая структура:


Информация о разделах хранится в таблице разделов. На диске может быть только 4 первичных раздела, с которых можно загрузиться. На запись о разделе приходится 8 байт. Первый байт — это флаги, если его значение 0x80, то раздел загрузочный. Код MBR в процессе своей работы пробегает по этим 4-м разделам в поиске загрузочного раздела. После его обнаружения, MBR копирует содержимое первого сектора этого раздела на адрес 0000h:7C00h и передает туда управление. Нас интересует LBA адрес первого сектора загрузочного раздела, так как именно на нем располагается наше ядро, и присутствует файловая система, которую мы собираемся читать. Для того чтобы получить этот адрес, нужно прочитать первый сектор диска, найти на нем таблицу разделов, в таблице разделов найти загрузочный раздел, а из его записи прочитать нужное поле.

Итак, у нас есть механизм для чтения сектора с диска и знание о расположении нужного нам раздела на диске. Осталось научиться работать с файловой системой на этом разделе.

Работа с файловой системой

Для работы с файловой системой мы будем использовать библиотеку fat_io_lib. Библиотека доступна под лицензией GPL. Она предоставляет интерфейс для работы с файлами и директориями, аналогичный имеющемуся в libc. Реализованы такие функции, как fopen(), fgets(), fputc(), fread(), fwrite() и т.д. Библиотека для своей работы требует всего лишь две функции: записать сектор и прочитать сектор, причем первая является необязательной. Функции имеют следующий прототип:

Библиотека написана на чистом С, что опять-таки нам на руку. Для использования в своей мини-ОС нам не придется менять в ней ни строчки. Библиотека ожидает, что чтение секторов происходит в рамках раздела с файловой системой.

Итак, у нас есть функции чтения/записи сектора на раздел и есть библиотека для работы с FAT16/32, которая использует эти функции. Осталось собрать все воедино и продемонстрировать результат. Но прежде чем перейти к коду, хотелось бы показать, что подход, который мы собираемся использовать, вполне применим в реальной жизни. Ниже представлена небольшая часть VBR windows 7, в которой происходит чтение сектора диска посредством прерывания int0x13. Этот код многократно вызывается в процессе загрузки системы, вплоть до момента отрисовки загрузочной анимации.


Для вызова этого кода, Windows 7, подобно тому, как это делаем мы, переходит из защищенного режима в реальный, и обратно. Это несложно проверить, запустив Windows 7 в QEMU. QEMU должен ожидать подключения отладчика. После подключения отладчика (gdb) ставим breakpoint на адрес (0x7c00 + 0x11d). Срабатывание breakpoint’а будет означать вызов этой функции. Кстати в Windows XP этот механизм отсутствует, для вызова прерываний BIOS'а там переходят в режим VM86.

! ВАЖНО! Все дальнейшие действия могут успешно осуществляться только после успешного прохождения всех шагов из пятой части нашей серии статей

Шаг 1. Изменим основную логику в kernel.c

1. Добавим в файле kernel.c следующие объявления:

Код, печатающий размер оперативной памяти

заменим на следующий код:

Память под переменные mbd и magic зарезервирована в файле loader.s, так что их можно использовать аналогично глобальным переменным из кода на С. Переменная magic содержит сигнатуру, подтверждающую, что для загрузки использовался стандарт Multiboot, эталонной реализацией которого является GRUB. Переменная mbd указывает на структуру multiboot_info_t, которая объявлена в multiboot.h. Номер загрузочного диска определяется следующим выражением — p_multiboot_info->boot_device >> 24. Функция InitBootMedia запоминает номер диска и ищет первый сектор файловой системы, чтобы затем все смещения считать от него.

Библиотека fat_io_lib для инициализации требует вызова двух функций: fl_init и fl_attach_media. Первая функция обнуляет внутренние структуры библиотеки, а вторая получает в качестве параметров функции чтения и записи секторов на диск, которые затем используются для обращения к файлам. Далее идет демонстрация работы с библиотекой: выводится список файлов в папке /boot/grub и распечатывается содержимое файла menu.lst.

2. Добавляем файл multiboot.h в папку include. Содержимое файла берем с сайта спецификации предыдущей версии.

Шаг 2. Добавим функции для работы с диском

1. В файл include\callrealmode.h добавим прототипы следующих функций:

2. В файле include\callrealmode_asm.h добавим в enum callrealmode_Func новое значение так, чтобы получилось следующее:

Добавим в union внутри структуры callrealmode_Data только что объявленную структуру callrealmode_read_disk. Должно получиться следующее:

3. В файл include\string.h добавим функции strncmp и strncpy, используемые в библиотеке fat_io_lib.

4. Добавим в файл callrealmode.c следующие объявления:

И несколько функций:

Функции ReadBootMedia и WriteBootMedia используются библиотекой fat_io_lib для чтения/записи секторов. Функция WriteBootMedia не обязательная и является заглушкой, так как в данном примере нет записи на диск. Ее реализация выглядела бы аналогично функции ReadBootMedia. Функция ReadBootMedia похожа на функцию GetRamsize из прошлой статьи с точностью до типа param.func, а вместо param.getsysmemmap используется param.readdisk. Функция InitBootMedia должна быть вызвана раньше двух остальных, так как она инициализирует значения g_BootPartitionStart и g_BootDeviceInt13Num.

5. Изменим callrealmode_asm.s. Добавим еще один тип CALLREALMODE_FUNC_READ_DISK вызываемых функций, должно получиться следующее:

Далее добавим еще одну проверку на тип функции и непосредственно код, читающий с диска. Должно получиться следующее:

Метка readdisk указывает на код, который формирует структуру DAP из структуры callrealmode_Data и вызывает int0x13. В коде после метки callrealmode_switch добавилось 2 инструкции, проверяющие, не нужно ли вызывать readdisk.

6. Добавим файл include\mbr.h, содержащий определения для работы с MBR. Его содержимое:

Структура MBRSector используется в функции InitBootMedia.

Шаг 3. Добавим библиотеку fat_io_lib и запустим

1. Скачаем архив fat_io_lib.zip и распакуем его в папку fat_io_lib в корне проекта.
2. Добавим пустые файлы assert.h и stdlib.h в папку include. Они нужны, что бы библиотека скомпилировалась.
3. Исправим Makefile. Добавим файлы из библиотеки в список целей для компиляции. Должно получиться следующее:


Теперь размер образа равен 10Mb. Это делается для того, чтобы команда mkdosfs отформатировала раздел в FAT16 вместо FAT12. FAT12 не поддерживается библиотекой fat_io_lib.

С этим дефайном библиотека не будет включать stdio.h, но будет использовать готовый прототип функции printf, который совпадает с нашим, и который уже реализован.

4. Пересоберем проект


sudo make image

Должно получиться следующее:


Как и в предыдущих частях, можно сделать dd образа hdd.img на флешку и проверить код на реальном железе, загрузившись с нее.

В результате мы реализовали работу с файловыми системами FAT16 и FAT32. Мы немного схитрили, использовав готовую библиотеку, но разбираться в устройстве FAT'а было бы менее интересно, да и вряд ли бы мы тогда уложились в 1 статью. Надеюсь, вам было интересно читать. Пишите в комментариях, если у вас возникнут проблемы в прохождении описанных шагов!

Я не уверен с тех пор, когда файловая система на моем цифровом аудиоплеере была изменена, чтобы быть доступной только для чтения. Я не могу копировать файлы в него или удалять файлы на нем.

Существуют ли возможные причины, по которым файловая система проигрывателя может изменить разрешение своей файловой системы?

Я пробовал chmod:

где «SGTL MSCN» - точка подключения цифрового аудиоплеера.

Мне было интересно, как сделать его доступным для записи?

Спасибо и всего наилучшего!

Спасибо! Я уже пробовал, и тот же вывод. Я добавлю это в свой пост. Не могли бы вы также добавить марку плеера? :) поиск 'SGTL MSN' на самом деле только поднимает эту тему: D Если вам действительно не повезло, это устройство прослушивается: в качестве последнего (!) средства перезагрузите плеер. Но только тогда, когда вы не получите хороших противников в ближайшее время (иш) :) Перепробовал все и нашел простое решение (еретик). Подключите USB к Windows 8 или 7, нажмите «восстановить внешний диск», вернитесь в Linux. Надеюсь, это кому-нибудь поможет.

Если файловая система была смонтирована только для чтения, chmod она не будет работать, так как это тоже операция записи.

Попробуйте перемонтировать его на чтение-запись:

Если на устройстве установлена ​​блокировка записи (например, карты памяти SD), его необходимо отключить. Аппаратные блокировки не могут быть отключены программным обеспечением. Обратите внимание, что блокировка записи на картах памяти SD расположена в том месте, где вы видите буквы рядом с левым верхним углом, и выглядит как очень маленький переключатель.

Некоторые драйверы файловой системы также могут не поддерживать операции записи, это имеет место со старым модулем NTFS, поддерживаемым Linux. Для файловых систем NTFS обязательно используйте ntfs-3g драйвер, который в настоящее время должен выбираться автоматически. Если нет, вы можете заставить драйвер что-то вроде:

(где /dev/sdb1 следует заменить ваше блочное устройство и /mnt/ пункт назначения)

Недавно, входе установки дистрибутива Zorin OS, я выделил и указал монтирование дополнительного раздела с файловой системой ext4. Как выяснилось после установки системы, раздел смонтирован, но права доступа на запись раздела есть только у Администратора (Root). Я не мог ничего скопировать в него или создать в нем папку. По всей видимости, у меня не было «прав на запись» для указанного раздела.

В этом руководстве мы рассмотрим, как правильно установить разрешение на запись для раздела с файловой системой ext4 в Ubuntu и подобных системах.

Как установить разрешение на запись в разделе ext4 для Ubuntu и подобных систем

Для начала нужно знать UUID раздела ext4. Но перед этим сначала стоит узнать имя раздела. Имя раздела в Ubuntu будет похоже на sdaX или sdbX для второго диска.

В терминале выполняем команду:

Вывод команды будет выглядеть примерно следующим образом:


Вы можете узнать название раздела по его размеру, указанному в поле Размер. В моем случае, т.к я смонтировал раздел второго диска, диск имеет название sdb1.

Теперь, когда вам известно имя раздела, вы можете найти UUID с помощью следующей команды:

Вывод команды будет выглядеть примерно так:


Как видите, по имени раздела можно легко определить UUID.

После того, как вы узнали UUID раздела, следующим шагом будет выяснить, где смонтирован раздел.

Примечание. Если точку монтирования раздела вы указали во время установки, то этот шаг пропустите.

Обычно расположение монтирования ext4 находится в /media/ . Где user_name – имя пользователя. Вы также можете использовать переменную $USER. Она автоматически примет имя пользователя.

Вы можете отобразить смонтированные разделы следующей командой:

У вас отобразятся смонтированные разделы. Вы также сможете видеть, что только root пользователь имеет право записи в смонтированном разделе ext4. Нам нужно будет изменить разрешение на запись для этого раздела.

Теперь самый простое решение – предоставить всем доступ на запись с помощью печально известного chmod 777. Но, опять же, вы не захотите этого делать, так как эти права предоставят всем доступ на запись. По возможности избегайте использования chmod 777.

А если не chmod 777, то что еще? Доступ к файлу есть у пользователя root как владельца и root как группы. Даже «admin» попадает в группу «другие». Поэтому решение прав доступа на запись ext4 раздела будет изменением группы владельца разделом.

Следующей командой мы изменим владельца раздела:

Где comss – имя пользователя, а 56d0c0ab-60a0-48bf-955d-bc2f283009b6 – UUID раздела.

В моем случае, т.к точка монтирования раздела была указана во время установки системы, то я поступил немного проще. Открыл файловый менеджер, перешел в раздел и в файловом менеджере посмотрел пусть расположения монтирования. Команда изменения группы владельца выглядела следующим образом: chgrp adm /Files

После изменения группы измените права записи для группы следующим образом:

Где comss – имя пользователя, а 56d0c0ab-60a0-48bf-955d-bc2f283009b6 – UUID раздела.

Опять же, в моем случае команда выглядела следующим образом: chmod g+w /Files


Теперь вы можете копировать, вставлять и создавать новые файлы в разделе ext4 без каких-либо проблем. А с дополнительной безопасностью пользователи без прав администратора не смогут этого сделать.

Использование NTFS-диска для игр из Steam в Linux

Данная инструкция необходима для настройки монтирования NTFS-диска, содержащего игры Steam, который ранее использовался в среде Windows, а дальше будет использоваться для работы с Proton (Steam Play) в Linux.

Данная инструкция взята из полезного материала репозитория ValveSoftware. В качестве протестированных систем там указаны различные версии Ubuntu и Pop!_OS, однако мною она была протестирована и в других Linux системах, и оказалась рабочей инструкцией.

Примечание. Если вы уже указали точку монтирования NTFS диска, например во время установки системы, то переходите сразу к следующую шагу, к редактированию fstab файла.

Настройка и автоматическое монтирование раздела NTFS

Создаем точку монтирования NTFS диска с играми:

Найдём идентификатор пользователя, идентификатор группы, раздел подключенного диска и UUID, используя следующие команды.

По умолчанию оба должны быть с номером 1000.

Примонтированный раздел диска:

Он должен быть помечен как /dev/sdaX

UUID: Найдите строку, в которой первый столбец соответствует метке команды fdisk.

Например, в моем случае это следующая строка:


Редактирование fstab

Отредактируйте файл fstab, чтобы смонтировать раздел или изменить параметры монтирования:

Для монтирования раздела добавьте следующую запись (если нет других записей для этого раздела):

Если опции монтирования уже заданы, то отредактируйте их и задайте из команды выше:


Командами CTRL+O и CTRL+X сохраните изменения и закройте редактор.

Предотвращение ошибок чтения NTFS

Из-за природы NTFS создание файлов / папок с символами, которые Windows не может прочесть, вызовает дисковые ошибки (что приведит к тому, что игры не запускаются), наиболее распространенной проблемой является символ ; в именах файлов, который Proton создает на диске NTFS.

Создание символической ссылки:

Где /media/gamedisk/ – это смонтированный NTFS диск.

Если папка /compatdata уже существует на смонтированном диске, то удалите её.

Исправление ошибки в работе с файлами

Причин возникновения проблем с доступом к файлам в Ubuntu может быть несколько.

Неисправность носителя

В первую очередь стоит проверить, точно ли исправна эта файловая система. В случае с флеш-картой сделать это легко. Попробуйте открыть её с компьютера на Windows. Другая система может быстро найти неполадки на накопителе. То же самое касается карт памяти, китайских плееров и других дешёвых носителей информации. Часто дело может быть в них.

В случае, когда проблемным является жёсткий диск, выполнить проверку будет гораздо труднее. Если на вашем компьютере стоит две системы, проверьте, исправно ли работает ваш HDD на Windows. Эти способы позволят определить очаг неисправности.

Форматирование

Во многих случаях вернуть работоспособность помогает простое форматирование файловой системы. Особенно легко это сделать на флешке. Правда, не всегда мы готовы расстаться с той информацией, которая на ней уже есть. Перекиньте все данные на компьютер под управлением Виндовс и отформатируйте проблемный накопитель.

С диском навряд ли у кого-то поднимется рука совершить такое. Форматирование может уничтожить много важной информации. Тем более, если повреждена файловая система Ubuntu, проблему надо искать в другом месте.

Форматирование диска

Проверка на наличие ошибок

Проверить диск на наличие ошибок можно не только на Windows. Убунту также обладает достаточным арсеналом для этого. Сделать это можно и с помощью команд, и пользуясь специальным приложением. Сначала разберём способ, использующий стандартные средства.

Просматриваем список накопителей:

Проверяем конкретный накопитель:

В примере взят sdf, но у вас название диска может отличаться.

Если том был примонтирован, то перед тем, как проверять, это действие нужно отменить:

Теперь проверяем том на бэдблоки — проблемные области:

Прогресс выполнения будет отображаться в процентах.

Теперь отмечаем бэдблоки, чтобы система перестала их использовать:

GParted

Загрузка приложения GParted

  1. Для начала эту программу необходимо установить. Сделать это легко при помощи команды:
    sudo apt-get install gparted
  2. Открываем GParted. Перед нами будут выведены все носители. Среди них должен быть и проблемный недоступный — если утилита увидит ошибки, то она пометит его восклицательным знаком.
  3. Теперь открываем наш диск и нажимаем на кнопку «Раздел», расположенную сверху.
  4. В выпавшем меню выбираем «Проверка на ошибки». Программа отсканирует диск и, возможно, найдёт неполадки, после чего файловая система станет доступной не только для чтения.

Права доступа

Наконец, последняя причина, по которой мы теряем доступ к управлению данными на носителях, заключается в нарушенных правах. С ней могут сталкиваться и опытные юзеры, использующие root-режим. Когда мы используем различные команды, не до конца понимая их суть, или запускаем программы с расширенными полномочиями, система может по ошибке перекрыть доступ.

Проверка прав доступа

В качестве универсального метода здесь подойдёт команда:

Вместо [user] необходимо вписать имя пользователя. Команда chown отвечает за смену прав доступа к папке. Атрибут –R означает, что этот раздел пользователь может только читать. Sudo отменяет эти изменения. В примере проблема заключалась в домашнем разделе, если у вас проблемы с флешкой, то следует вписать её директорию.

Файловая система Убунту работает немного по другим принципам, нежели на Windows. Поэтому любые диски под её управлением ведут себя по-другому. Из-за этого возникают и новые ошибки, с которыми на Винде нельзя столкнуться.

Читайте также: