Ответ 1
По иронии судьбы, я сегодня столкнулся с этой же проблемой.
В моем случае ответ пришел к тому, какой уровень гранулярности разрешения мне нужен в Windows, по сравнению с Linux. В моем случае, я только забочусь о пользователях, группах и других разрешениях на Linux. В Windows основное чтение Read/Write All, оставшееся от DOS, достаточно для меня, то есть мне не нужно иметь дело с ACL в Windows.
Вообще говоря, Windows имеет две модели привилегий: базовую модель DOS и более новую модель управления доступом. В модели DOS существует один тип привилегий: write privilege. Все файлы могут быть прочитаны, поэтому нет возможности отключить разрешение на чтение (потому что оно не существует). Также нет понятия разрешения на выполнение. Если файл может быть прочитан (ответ "да" ), и он двоичный, то он может быть выполнен; иначе он не может.
Основная DOS-модель достаточна для большинства сред Windows, то есть в средах, где система используется одним пользователем в физическом местоположении, которое можно считать относительно безопасным. Модель управления доступом более сложна на несколько порядков.
Модель управления доступом использует списки управления доступом (ACL) для предоставления привилегий. Привилегии могут предоставляться только процессом с необходимыми привилегиями. Эта модель не только позволяет управлять пользователями, группами и другими с разрешениями чтения, записи и выполнения, но также позволяет управлять файлами по сети и между доменами Windows. (Вы также можете получить этот уровень безумия в Unix-системах с PAM.)
Примечание. Модель управления доступом доступна только на разделах NTFS, если вы используете разделы FAT, вы являетесь SOL.
Использование ACL - большая боль в заднице. Это не тривиальное начинание, и вам потребуется узнать не только ACL, но и все о дескрипторах безопасности, токенах доступа и множестве других передовых концепций безопасности Windows.
К счастью для меня, для моих текущих потребностей, мне не нужна настоящая безопасность, предоставляемая моделью управления доступом. Я могу обойтись, в основном делая вид, что устанавливаю разрешения для Windows, если я действительно устанавливаю разрешения для Linux.
Windows поддерживает то, что они называют "совместимой с 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, когда вы даете разрешение группе или другому (или удаляете ее в этом отношении), вы действительно меняете владельца. Если вы не хотите этого делать, но вам все равно не нужны полные разрешения ACL Windows, просто определите STRICT_UGO_PERMISSIONS.