Как установить полномочия файла (кросс-платформенные) в C++?

Я использую C++ ofstream выписать файл. Я хочу установить полномочия быть только доступным пользователем: 700. В Unix; я предполагаю, что могу просто проблема a system("chmod 700 file.txt"); но мне нужен этот код для работы над Windows также. Я могу использовать некоторый API Windows; но каков лучший C++ кросс-платформенный способ сделать это?

22
задан jww 24 September 2019 в 15:16
поделиться

7 ответов

Как ни странно, я только что столкнулся с этой точно той же потребностью ранее сегодня.

В моем случае, ответ свелся к тому, в каком уровне гранулярности разрешения я нуждаюсь в Windows, по сравнению с Linux. В моем случае я только забочусь о Пользователе, Группе и Другом разрешении на Linux. В Windows основное Чтение-запись Весь остаток разрешения от DOS достаточно хорош для меня, т.е. Я не должен иметь дело с ACL в Windows.

Вообще говоря, Windows имеет две модели полномочия: основная модель DOS и более новая модель управления доступом. Под моделью DOS существует один тип полномочия: запишите полномочие. Все файлы могут быть считаны, таким образом, нет никакого способа выключить разрешение чтения (потому что оно не существует). Нет также никакого понятия, выполняют разрешение. Если файл может быть считан (ответ - да), и это является двоичным, то он может быть выполнен; иначе это не может.

основная модель DOS достаточна для большинства сред Windows, т.е. сред, где система используется отдельным пользователем в физическом месте, которое можно считать относительно безопасным. Модель управления доступом более сложна несколькими порядками величины.

модель управления доступом использует списки управления доступом (ACL) для предоставления полномочий. Полномочия может только предоставить процесс с необходимыми полномочиями. Эта модель не только позволяет управление Пользователя, Группы и Другого с Чтением, Записью, и Выполните разрешение, но это также позволяет управление файлов по сети и между доменами Windows. (Можно также получить этот уровень безумия в системах Unix с PAM.)

Примечание: модель Access Control только доступна на разделах NTFS при использовании разделов FAT, Вы - СОЛЬ.

Используя ACL большая боль в заднице. Это не тривиальное обязательство, и это потребует, чтобы Вы изучили не только ACL, но также и все о Дескрипторах безопасности, Маркерах доступа и большом из других усовершенствованных понятий безопасности Windows.

, К счастью, для меня, для моих текущих потребностей, мне не нужна истинная безопасность, которую обеспечивает модель управления доступом. Я могу обойтись в основном притворством установить полномочия в Windows, пока я действительно установил полномочия на Linux.

Windows поддерживает то, что они называют "C++ ISO совместимой" версией chmod (2). Этот API называют _chmod, и это подобно chmod (2), но более ограничено и не тип или имя, совместимое (конечно). Windows также имеет chmod устаревший, таким образом, Вы не можете просто добавить chmod к Windows и использовать прямой chmod (2) на Linux.

я записал следующее:

#include <sys/stat.h>
#include <sys/types.h>

#ifdef _WIN32
#   include <io.h>

typedef int mode_t;

/// @Note If STRICT_UGO_PERMISSIONS is not defined, then setting Read for any
///       of User, Group, or Other will set Read for User and setting Write
///       will set Write for User.  Otherwise, Read and Write for Group and
///       Other are ignored.
///
/// @Note For the POSIX modes that do not have a Windows equivalent, the modes
///       defined here use the POSIX values left shifted 16 bits.

static const mode_t S_ISUID      = 0x08000000;           ///< does nothing
static const mode_t S_ISGID      = 0x04000000;           ///< does nothing
static const mode_t S_ISVTX      = 0x02000000;           ///< does nothing
static const mode_t S_IRUSR      = mode_t(_S_IREAD);     ///< read by user
static const mode_t S_IWUSR      = mode_t(_S_IWRITE);    ///< write by user
static const mode_t S_IXUSR      = 0x00400000;           ///< does nothing
#   ifndef STRICT_UGO_PERMISSIONS
static const mode_t S_IRGRP      = mode_t(_S_IREAD);     ///< read by *USER*
static const mode_t S_IWGRP      = mode_t(_S_IWRITE);    ///< write by *USER*
static const mode_t S_IXGRP      = 0x00080000;           ///< does nothing
static const mode_t S_IROTH      = mode_t(_S_IREAD);     ///< read by *USER*
static const mode_t S_IWOTH      = mode_t(_S_IWRITE);    ///< write by *USER*
static const mode_t S_IXOTH      = 0x00010000;           ///< does nothing
#   else
static const mode_t S_IRGRP      = 0x00200000;           ///< does nothing
static const mode_t S_IWGRP      = 0x00100000;           ///< does nothing
static const mode_t S_IXGRP      = 0x00080000;           ///< does nothing
static const mode_t S_IROTH      = 0x00040000;           ///< does nothing
static const mode_t S_IWOTH      = 0x00020000;           ///< does nothing
static const mode_t S_IXOTH      = 0x00010000;           ///< does nothing
#   endif
static const mode_t MS_MODE_MASK = 0x0000ffff;           ///< low word

static inline int my_chmod(const char * path, mode_t mode)
{
    int result = _chmod(path, (mode & MS_MODE_MASK));

    if (result != 0)
    {
        result = errno;
    }

    return (result);
}
#else
static inline int my_chmod(const char * path, mode_t mode)
{
    int result = chmod(path, mode);

    if (result != 0)
    {
        result = errno;
    }

    return (result);
}
#endif

важно помнить, что мое решение только обеспечивает безопасность типа DOS. Это не также известно как никакая безопасность, но это - сумма безопасности, которую большинство приложений дает Вам в Windows.

кроме того, согласно моему решению, если Вы не определяете STRICT_UGO_PERMISSIONS при предоставлении разрешения сгруппироваться или другой (или удалить его в этом отношении) Вы действительно изменяете владельца. Если Вы не хотели делать это, но Вы все еще не нуждались в полных полномочиях Windows ACL, просто определили STRICT_UGO_PERMISSIONS.

29
ответ дан 29 November 2019 в 04:23
поделиться

Нет никакого межплатформенного способа сделать это. Windows не поддерживает полномочия файла стиля Unix. Чтобы сделать то, что Вы хотите, необходимо будет изучить создание списка управления доступом для того файла, который позволит Вам явно определить права доступа для пользователей и групп.

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

8
ответ дан 29 November 2019 в 04:23
поделиться

Эти system() вызов является странным зверем. Я был укушен системой NOP () реализация на Mac много лун назад. Это - определенное значение реализации, что стандарт не определяет то, что реализация (платформа/компилятор), как предполагается, делает. К сожалению, это также о единственном стандартном способе сделать что-то вне объема Вашей функции (в Вашем случае - изменение полномочий).

Обновление: А предложил взлом:

  • Создают непустой файл с соответствующими полномочиями в Вашей системе.
  • Файловая система Повышения Использования copy_file для копирования этого файла к желаемому выводу.

    void copy_file(const path& frompath, const path& topath): содержание и атрибуты файла, упомянутого frompath, копируются в файл, упомянутый topath. Эта стандартная программа ожидает, что целевой файл будет отсутствовать; если целевой файл присутствует, он выдает исключение. Это, поэтому, не эквивалентно определенной команде CP системы в UNIX. Также ожидается, что frompath переменная относилась бы к надлежащему регулярному файлу. Рассмотрите этот пример: frompath относится к символьной ссылке/tmp/file1, который в свою очередь относится к файлу/tmp/file2; topath, скажем,/tmp/file3. В этой ситуации перестанет работать copy_file. Это - еще одно различие, которым управляет этот API спорт по сравнению с CP.

  • Теперь, перезапишите вывод с фактическим содержанием.

, Но, это - только взлом, о котором я думал далеко за полночь. Возьмите его с щепоткой соли и испытайте это:)

3
ответ дан 29 November 2019 в 04:23
поделиться

Никакая идея, если это работало бы, но Вы могли бы изучить использование chmod.exe исполняемый файл, который идет с Cygwin.

1
ответ дан 29 November 2019 в 04:23
поделиться

Нет никакого стандартного способа сделать это в C++, но для этого особого требования необходимо, вероятно, просто записать пользовательскую обертку с #ifdef _WIN32. QT имеет обертку разрешения в, он класс QFile , но это, конечно, означало бы в зависимости от QT

1
ответ дан 29 November 2019 в 04:23
поделиться

Вы не можете сделать этого межплатформенным способом. В Linux необходимо использовать функцию chmod(2) вместо того, чтобы использовать system(2) для порождения новой оболочки. В Windows необходимо будет использовать различное функции авторизации для создания ACL (список контроля доступа) с верными полномочиями.

0
ответ дан 29 November 2019 в 04:23
поделиться

Я только что нашел несколько способов легко выполнить chmod 700 из командной строки Windows. Я собираюсь опубликовать еще один вопрос с просьбой о помощи в разработке эквивалентной структуры дескриптора безопасности win32 для использования (если я не смогу понять это в следующие несколько часов).

Windows 2000 и XP (беспорядок - это всегда кажется, подсказывает):

echo Y|cacls *onlyme.txt* /g %username%:F

Windows 2003 +:

icacls *onlyme.txt* /inheritance:r /grant %username%:r

РЕДАКТИРОВАТЬ:

Если у вас была возможность использовать ATL, эта статья описывает это (у меня нет Visual Studio): http://www.codeproject.com/KB/winsdk/accessctrl2.aspx

На самом деле, там говорится, что образец кода также включает образец кода, не относящегося к ATL - в нем должно быть что-то, что работает для вас (и меня !)

Важно помнить, чтобы получить r / w / x для владельца только на win32, вам просто нужно стереть все дескрипторы безопасности из файла и добавить один для себя с полным контролем.

1
ответ дан 29 November 2019 в 04:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: