Sto usando C++ ofstream
per scrivere un file. Voglio impostare le autorizzazioni affinché siano accessibili solo dall'utente: 700. In unix; Suppongo di poter emettere uno system("chmod 700 file.txt");
ma ho bisogno che questo codice funzioni anche su Windows. Posso usare alcune API di Windows; ma qual è il modo migliore in cui C++ può fare questo cross platform?C++ - Come impostare i permessi dei file (multipiattaforma)
risposta
Ironia della sorte, mi sono imbattuto in questa stessa necessità prima di oggi.
Nel mio caso, la risposta è arrivata a quale livello di granularità dei permessi ho bisogno su Windows, contro Linux. Nel mio caso, mi interessa solo l'autorizzazione Utente, Gruppo e Altro su Linux. Su Windows, il permesso di lettura/scrittura di base di tutti gli avanzi da DOS è abbastanza buono per me, cioè non ho bisogno di trattare con ACL su Windows.
In generale, Windows dispone di due modelli privilegiati: il modello DOS di base e il modello di controllo di accesso più recente. Sotto il modello DOS c'è un tipo di privilegio: privilegio di scrittura. Tutti i file possono essere letti, quindi non c'è modo di disattivare il permesso di lettura (perché non esiste). Non esiste anche alcun concetto di permesso di esecuzione. Se un file può essere letto (la risposta è sì) ed è binario, allora può essere eseguito; altrimenti non può.
Il modello DOS di base è sufficiente per la maggior parte degli ambienti Windows, vale a dire ambienti in cui il sistema viene utilizzato da un singolo utente in un luogo fisico che può essere considerato relativamente sicuro. Il modello di controllo degli accessi è più complesso di diversi ordini di grandezza.
Il modello di controllo di accesso utilizza gli elenchi di controllo di accesso (ACL) per concedere i privilegi. I privilegi possono essere concessi solo da un processo con i privilegi necessari. Questo modello non solo consente il controllo di Utente, Gruppo e Altro con autorizzazione Lettura, Scrittura ed Esecuzione, ma consente anche il controllo dei file sulla rete e tra i domini Windows. (È possibile anche ottenere questo livello di follia su sistemi Unix con PAM.)
Nota: Il modello di controllo di accesso è disponibile solo su partizioni NTFS, se si utilizza partizioni FAT sei SOL.
Utilizzo ACL è un grande dolore nel culo. Non è un'impresa banale e richiede che tu impari non solo l'ACL, ma anche tutti i descrittori di sicurezza, i token di accesso e un sacco di altri concetti avanzati di sicurezza di Windows.
Fortunatamente per me, per le mie esigenze attuali, non ho bisogno la vera sicurezza che il modello di controllo di accesso fornisce. Riesco a passare fondamentalmente facendo finta di impostare le autorizzazioni su Windows, a patto che imposti realmente le autorizzazioni su Linux.
Windows supporta quello che chiamano un versione "ISO C++ conforme" di chmod (2). Questa API è chiamata _chmod ed è simile a chmod (2), ma più limitata e non di tipo o nome compatibile (ovviamente). Windows ha anche un chmod deprecato, quindi non puoi semplicemente aggiungere chmod a Windows e usare il chmod dritto (2) su Linux.
ho scritto il seguente:
#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
E 'importante ricordare che la mia soluzione prevede solo DOS di sicurezza tipo. Questo è anche noto come non sicurezza, ma è la quantità di sicurezza che la maggior parte delle app ti dà su Windows.
Inoltre, sotto la mia soluzione, se non definisci STRICT_UGO_PERMISSIONS, quando dai il permesso al gruppo o ad altro (o lo rimuovi per questo), stai davvero cambiando il proprietario. Se non vuoi farlo, ma non hai ancora bisogno di autorizzazioni ACL complete per Windows, basta definire STRICT_UGO_PERMISSIONS.
Non esiste un modo multipiattaforma per eseguire questa operazione. Windows non supporta i permessi dei file in stile Unix. Per fare ciò che vuoi, dovrai cercare di creare un elenco di controllo di accesso per quel file, che ti consentirà di definire esplicitamente le autorizzazioni di accesso per utenti e gruppi.
Un'alternativa potrebbe essere quella di creare il file in una directory le cui impostazioni di sicurezza sono già state impostate per escludere tutti tranne l'utente.
Questa risposta è qualcosa a cui le persone dovrebbero davvero pensare: il trattamento delle autorizzazioni nelle app è davvero necessario? In molti, molti casi non lo è e addirittura rompe le cose, perché consente ad amministratori e utenti di controllare le autorizzazioni come meglio credono. Soprattutto per es. su Windows, nessun altro utente è in grado di accedere alle directory home dell'utente in ogni caso, quindi probabilmente non è necessario rendere i file "privati" manualmente. Un sacco di chmod + umask-handling nelle applicazioni Linux è legacy a causa della mancanza di ACL, ereditarietà adeguata e così via. Cerca di evitarlo il più possibile. –
Non c'è un modo standard per farlo in C++, ma per questo requisito speciale probabilmente dovresti scrivere solo un wrapper personalizzato, con #ifdef _WIN32. Qt ha un wrapper di autorizzazione nella sua classe QFile, ma ciò ovviamente significherebbe in base a Qt ...
L'avviso sul collegamento fornito implica che questo potrebbe non funzionare come previsto su Windows. – Ferruccio
Non è possibile farlo in modo multipiattaforma. In Linux, dovresti usare la funzione chmod(2)
invece di usare system(2)
per generare una nuova shell. Su Windows, dovrai usare i vari authorization functions per creare un ACL (access-control list) con le autorizzazioni appropriate.
La chiamata system()
è una strana bestia. Sono stato morso da un'implementazione di un sistema NOP() su un Mac molte lune fa. La sua implementazione è definita dal fatto che lo standard non definisce cosa un'implementazione (piattaforma/compilatore) dovrebbe fare. Sfortunatamente, questo è anche l'unico modo standard per fare qualcosa al di fuori della portata della tua funzione (nel tuo caso - cambiare i permessi).
Aggiornamento: A proposto mod:
- Creare un file non vuoto con le autorizzazioni appropriate sul vostro sistema.
Utilizzare Boost Filesystem
copy_file
per copiare questo file nell'output desiderato.void copy_file(const path& frompath, const path& topath)
: I contenuti e attributi del file a cui si riferisce frompath vengono copiati il file a cui si riferisce topath. Questa routine si aspetta che un file di destinazione sia assente; se il file di destinazione è presente, genera un'eccezione. Questo, quindi, non è equivalente al comando cp specificato dal sistema in UNIX. Si prevede inoltre che la variabile frompath faccia riferimento a un file regolare appropriato. Considera questo esempio: frompath fa riferimento a un link simbolico/tmp/file1, che a sua volta si riferisce a un file/tmp/file2; topath è, per esempio,/tmp/file3. In questa situazione, copy_file fallirà. Questa è un'altra differenza rispetto a questa API rispetto al comando cp.Ora, sovrascrivere l'output con i contenuti effettivi.
Ma, questo è solo un hack ho pensato a lungo dopo la mezzanotte. Prendilo con un pizzico di sale e provalo :)
Ho appena trovato un paio di modi per fare chmod 700 facilmente dalla riga di comando di Windows. Inserirò un'altra domanda per chiedere aiuto su una struttura di descrittore di sicurezza win32 equivalente da usare (se non riesco a capirlo nelle prossime ore).
Windows 2000 & XP (messy- sembra sempre per richiedere):
echo Y|cacls *onlyme.txt* /g %username%:F
di Windows 2003+:
icacls *onlyme.txt* /inheritance:r /grant %username%:r
EDIT:
Se avete avuto la possibilità di utilizzare l'ATL, questo articolo lo copre (non sono disponibili Visual Studio): http://www.codeproject.com/KB/winsdk/accessctrl2.aspx
In realtà, dice il codice di esempio include la non-ATL codice di esempio, come ben si dovrebbe avere qualcosa che funziona per voi (e me!)
La cosa importante da ricordare è quello di ottenere r/w/x per il proprietario solo su win32, devi solo cancellare tutti i descrittori di sicurezza dal file e aggiungerne uno per te con il pieno controllo.
Esempio multipiattaforma per impostare 0700 per un file con C++ 17 e il suo std::filesystem
.
#include <exception>
//#include <filesystem>
#include <experimental/filesystem> // Use this for most compilers as of yet.
//namespace fs = std::filesystem;
namespace fs = std::experimental::filesystem; // Use this for most compilers as of yet.
int main()
{
fs::path myFile = "path/to/file.ext";
try {
fs::permissions(myFile, fs::perms::owner_all); // Uses fs::perm_options::replace.
}
catch (std::exception& e) {
// Handle exception or use another overload of fs::permissions()
// with std::error_code.
}
}
Vedi std::filesystem::permissions
, std::filesystem::perms
e std::filesystem::perm_options
.
- 1. Come posso impostare i permessi dei file da Perl?
- 2. Come garantire i permessi dei file corretti
- 3. I permessi dei file non ereditano i permessi delle directory
- 4. cmake: come modificare i permessi dei file durante l'installazione?
- 5. Come posso cambiare i permessi dei file in Ubuntu
- 6. imposta i permessi dei file nel file setup.py
- 7. Impossibile impostare i permessi dei file in S3 usando boto e django
- 8. aperti i permessi dei file() non correttamente l'impostazione
- 9. Regex per i permessi dei file Linux (notazione numerica)
- 10. Stampa dei permessi dei file come 'ls -l' usando stat (2) in C
- 11. permessi dei file Java per le discussioni
- 12. MSI Installer permessi file/cartella
- 13. Verifica dei permessi dei file in Linux con Python
- 14. Modifica dei permessi su/vagabondo
- 15. Come rilevare i permessi dei file durante l'estrazione del file tar?
- 16. EKEventStore prompt dei permessi
- 17. JavaFX FileChooser: come impostare i filtri dei file?
- 18. Come impostare (unix) i permessi durante la creazione di un file in SAP ABAP?
- 19. permessi dei file mkfifo non essere eseguiti correttamente
- 20. Come eseguire l'I/O su file asincrono multipiattaforma in C++
- 21. django/file upload permessi
- 22. Come definire i permessi di Amazon S3
- 23. In che modo Subversion gestisce i permessi dei file e un file .htaccess?
- 24. Implementazione multipiattaforma C# di Lua
- 25. Inno Setup - Come impostare i permessi completi su una cartella, non solo per il suo contenuto
- 26. Mantenere i permessi dei file durante l'estrazione da un file zip usando JDK 5 api
- 27. Come ottenere i permessi di scrittura del registro in C#
- 28. SBT: modo multipiattaforma per impostare java.library.path?
- 29. Impostazione dei permessi sui file sul contenuto del tarfile
- 30. fopen Crea file, ma come modificare i permessi?
Orribile! Insicuro! Non creare il file, quindi correggere le sue autorizzazioni in seguito - e tanto meno usando un pazzo hack come 'system (" chmod ")'. Invece fallo nel modo giusto, creando autorizzazioni restrittive e usa un'API senza gara. Usa 'umask' (non thread-safe) o' open + fchmod + fdopen + std :: fstream'. –
Non c'è niente di sbagliato nell'uso di chmod, purché chmod sia usato prima di scrivere i dati sensibili sul file. Ti rendi conto nella tua "risposta" che fchmod() è molto simile a chmod, giusto? – samoz