Использование chmod в программе на C - PullRequest
15 голосов
/ 31 декабря 2010

У меня есть программа, в которой мне нужно установить права доступа к файлу (скажем, /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 Ответ

33 голосов
/ 31 декабря 2010

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

Для восьмеричного преобразования используйте strtol() (или, как Крис Джестер-Янг указывает, 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 сохранил нулевой терминал - плохо!Используйте:

    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.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...