Использование chmod в программе C

У меня есть программа, где мне нужно установить права доступа к файлу (скажем /home/hello.t) с помощью chmod, и мне нужно прочитать разрешения, которые должны быть установлены из файла. Для этого я сначала прочитал разрешения в массиве символов, а затем попытаюсь изменить разрешения файла. Но я вижу, что разрешения заданы странным образом.

Пример программы, которую я написал:

main()
{
    char mode[4]="0777";
    char buf[100]="/home/hello.t";
    int i;
    i = atoi(mode);
    if (chmod (buf,i) < 0)
        printf("error in chmod");
}

Я вижу, что разрешения для файла не установлены на 777. Не могли бы вы помочь мне узнать, как установить разрешения файла после прочтения этого же из массива символов.

Ответ 1

Функция atoi() преобразует только десятичную, а не восьмеричную.

Для восьмеричного преобразования используйте strtol() (или, как Chris Jester-Young, strtoul() - хотя допустимые размеры режимов разрешения файлов для Unix все они соответствуют 16 бит, и поэтому никогда не будут давать отрицательный long) с 0 или 8 в качестве базы. На самом деле, в этом контексте лучше всего указать 8. Это позволяет людям писать 777 и получать правильное восьмеричное значение. При заданной базе 0 строка 777 является десятичной (снова).


Дополнительно:

  • Не используйте возвращаемый тип 'implicit int' для main(); быть явным, как требуется C99, и использовать int main(void) или int main(int argc, char **argv).
  • Не играйте с измельчением завершающих нулей с вашей строки.

    char mode[4] = "0777";
    

    Это не позволяет C хранить терминал null - плохо! Использование:

    char mode[] = "0777";
    

    Это выделяет 5 байт, необходимых для хранения строки с нулевым терминатором.

  • Сообщить об ошибках stderr, а не stdout.

  • Сообщить об ошибках с новой строкой в ​​конце.
  • Хорошей практикой является включение имени и имени программы в сообщение об ошибке, а также (как указывалось CJY), чтобы включить номер системной ошибки и соответствующую строку на выходе. Для этого требуется заголовок <string.h> (для strerror()) и <errno.h> для errno. Кроме того, статус выхода программы должен указывать на сбой при выполнении операции chmod().

Ввод всех изменений вместе дает:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>

int main(int argc, char **argv)
{
    char mode[] = "0777";
    char buf[100] = "/home/hello.t";
    int i;
    i = strtol(mode, 0, 8);
    if (chmod (buf,i) < 0)
    {
        fprintf(stderr, "%s: error in chmod(%s, %s) - %d (%s)\n",
                argv[0], buf, mode, errno, strerror(errno));
        exit(1);
    }
    return(0);
}

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

Обратите внимание, что код не выполняет проверку ошибок на результат strtol(). В этом контексте он достаточно безопасен; если пользователь предоставил это значение, было бы плохой идеей доверять им, чтобы все было правильно.


Один последний комментарий: обычно вы не должны использовать разрешение 777 для файлов (или каталогов). Для файлов это означает, что вы не возражаете, кто может изменить вашу исполняемую программу или как это сделать. Обычно это не так; вы заботитесь (или должны заботиться), кто изменяет ваши программы. Как правило, не делайте исполняемые файлы данных вообще; когда файлы исполняемы, не предоставляйте публичный доступ на запись и не смотрите на доступ к группе для записи. Для каталогов публичное разрешение записи означает, что вы не возражаете, кто удаляет какие-либо файлы в каталоге (или добавляет файлы). Опять же, иногда это может быть правильная настройка разрешения для использования, но это очень редко. (Для каталогов обычно рекомендуется использовать "липкий бит": разрешение 1777 - это то, что обычно используется на /tmp, например, но не на MacOS X.)