Редактирование записи /etc/fstab в C++

Я пытаюсь отредактировать файл /etc/fstab в установке CentOS с помощью С++. Идея состоит в том, что на основе другого файла конфигурации я добавлю записи, которых нет в fstab, или отредактирую записи в файле fstab, где точка монтирования такая же. Это позволяет нам правильно настроить систему при начальной загрузке.

Я нашел setmntent() и getmntent() для перебора существующих записей, поэтому я могу легко проверить, существует ли запись в fstab в моем файле конфигурации. Затем я могу использовать addmntent() для добавления любой несуществующей записи - в документации ничего не говорится о возможности редактирования записи, только добавление новой записи в конец файла. Кажется, нет возможности отредактировать существующую запись или удалить запись. Кажется странным, что этой функции не существует, только CR, а не UD CRUD.

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

Моя другая альтернатива:

  • открыть файл с помощью setmntent()
  • прочитать весь fstab в память с помощью getmentent() и выполнить любые добавления и/или правки
  • закрыть файл с помощью endmntent()
  • открыть /etc/fstab для записи
  • закрыть /etc/fstab (таким образом очистив файл)
  • откройте fstab с помощью setmntent()
  • прокручивать записи, которые я читал ранее, и записывать их, используя addmntent()

Что, хотя, вероятно, хорошо, просто кажется немного грязным.


person fwg    schedule 07.12.2010    source источник
comment
переместите текущий файл в резервную копию вместо усечения.   -  person Paulo Scardine    schedule 07.12.2010


Ответы (1)


При изменении файлов конфигурации системы, таких как /etc/fstab, имейте в виду, что они находятся в критическом состоянии, и если ваше «редактирование» будет прервано сбоем питания, это может привести к сбою перезагрузки.
Способ справиться с этим:

  1. создать пустой вывод:
    FILE* out = setmntent("/etc/fstab.new", "rw");
  2. открыть оригинал для ввода:
    FILE* in = setmntent("/etc/fstab", "r");
  3. скопируйте содержимое:
    while (m = getmntent(in)) { addmntent(out, m); }
  4. убедитесь, что в выводе есть все:
    fflush(out); endmntent(out); endmntent(in);
  5. атомарно заменить /etc/fstab:
    rename("/etc/fstab.new", "/etc/fstab");

Читателю предлагается в качестве упражнения изменить тело цикла while, чтобы внести изменения в существующий элемент, заменить специально созданный mntent или что-то еще. Если есть конкретные вопросы по этому поводу, задавайте.

Семантика UN*X для rename() гарантирует, что даже в случае потери питания у вас будет либо исходная версия, либо новая обновленная версия.

Есть причина, по которой нет modifymntent(), потому что это будет способствовать плохому программированию / плохим способам изменения системных критических файлов. Вы говорите в конце своего поста "... наверное хорошо..." - нет. Единственный безопасный способ изменить файл конфигурации системы — это написать полную измененную копию, синхронизировать ее с безопасным хранилищем, а затем использовать переименование для замены старой.

person FrankH.    schedule 07.12.2010
comment
Это то, что я собирался сделать, я просто упростил это, чтобы проиллюстрировать суть. Я думаю, что отсутствие modifymntent() поощряет плохие способы делать вещи, потому что люди будут писать свои собственные синтаксические анализаторы и делать то, что вы только что сделали. предупредил о. Гораздо лучше иметь функцию, которая сделает все это за вас. - person fwg; 07.12.2010
comment
В первоначальном вопросе говорилось, что вы действительно планировали написать /etc/fstab. Как уже упоминалось, это ключевой шаг, которого следует избегать. Запишите новый файл. Как вы говорите, функции *mntent() нельзя использовать ни для чего другого, кроме как для чистого ввода/вывода. Это то, что я пытался заявить: это по замыслу/намерению! Следовательно, использование двух файлов — чтение из /etc/fstab, запись в /etc/fstab.new, после чего сброс и переименование. На языке C++ вы бы назвали getmntent() константным итератором прямого ввода и addmntent() итератором прямого вывода. Примечание: ни случайное, ни двунаправленное. - person FrankH.; 07.12.2010
comment
Если вы посмотрите на это с точки зрения свойств итератора, то также станет ясно, что константный итератор прямого ввода означает, что вы не можете модифицировать файл, который вы проходите через него. Для упомянутого шаблона ввод и вывод не могут быть одним и тем же файлом. - person FrankH.; 07.12.2010
comment
Извините за путаницу, когда я сказал написать, я имел в виду, что это была конечная цель, иметь новый fstab. Я так понимаю он рассчитан только на ввод/вывод. Я все еще думаю, что отсутствие функции модификации и предоставление возможности ее выполнения программисту для выполнения любого старого мусора, вместо того, чтобы инкапсулировать все, что вы предложили, в один простой вызов функции, - это Плохая вещь. - person fwg; 09.12.2010