2009-02-26 14 views
19

मैं फ़ाइल लिखने के लिए C++ ofstream का उपयोग कर रहा हूं। मैं उपयोगकर्ता द्वारा केवल एक्सेस करने के लिए अनुमतियां सेट करना चाहता हूं: 700. यूनिक्स में; मुझे लगता है कि मैं सिर्फ system("chmod 700 file.txt"); जारी कर सकता हूं लेकिन मुझे विंडोज़ पर भी काम करने के लिए इस कोड की आवश्यकता है। मैं कुछ विंडोज एपीआई का उपयोग कर सकते हैं; लेकिन ऐसा करने के लिए सबसे अच्छा सी ++ क्रॉस प्लेटफ़ॉर्म तरीका क्या है?सी ++ - फ़ाइल अनुमतियां कैसे सेट करें (क्रॉस प्लेटफ़ॉर्म)

+0

भयानक! असुरक्षित! फ़ाइल न बनाएं, उसके बाद इसकी अनुमतियों को ठीक करें - अकेले एक पागल हैक जैसे 'सिस्टम ("chmod") का उपयोग करें। इसके बजाय इसे प्रतिबंधित तरीके से बनाएं और रेस-फ्री एपीआई का उपयोग करें। 'Umask' (थ्रेड-सुरक्षित नहीं) या 'ओपन + fchmod + fdopen + std :: fstream' का प्रयोग करें। –

+0

chmod का उपयोग करने में कुछ भी गलत नहीं है, जब तक कि फ़ाइल में संवेदनशील डेटा लिखने से पहले chmod का उपयोग किया जाता है। आप अपने "उत्तर" में महसूस करते हैं कि fchmod() chmod के समान है, है ना? – samoz

उत्तर

23

विडंबना यह है कि, मैंने आज भी इसी तरह की आवश्यकता में भाग लिया है।

मेरे मामले में, उत्तर लिनक्स बनाम विंडोज़ पर मुझे किस स्तर की अनुमति ग्रैन्युलरिटी की आवश्यकता है। मेरे मामले में, मुझे केवल लिनक्स पर उपयोगकर्ता, समूह और अन्य अनुमति की परवाह है। विंडोज़ पर, मूल पढ़ें/लिखें डॉस से सभी अनुमति बचे हुए मेरे लिए काफी अच्छा है, यानी मुझे विंडोज़ पर एसीएल से निपटने की जरूरत नहीं है।

आम तौर पर, विंडोज के दो विशेषाधिकार मॉडल हैं: मूल डॉस मॉडल और नया एक्सेस कंट्रोल मॉडल। डॉस मॉडल के तहत एक प्रकार का विशेषाधिकार है: विशेषाधिकार लिखें। सभी फाइलें पढ़ी जा सकती हैं, इसलिए पढ़ने की अनुमति को बंद करने का कोई तरीका नहीं है (क्योंकि यह अस्तित्व में नहीं है)। निष्पादन अनुमति की कोई अवधारणा भी नहीं है। अगर एक फ़ाइल पढ़ी जा सकती है (उत्तर हाँ है) और यह बाइनरी है, तो इसे निष्पादित किया जा सकता है; अन्यथा यह नहीं कर सकता है।

मूल डॉस मॉडल अधिकांश विंडोज वातावरण के लिए पर्याप्त है, यानी वातावरण जहां सिस्टम को एक भौतिक स्थान में एक उपयोगकर्ता द्वारा उपयोग किया जाता है जिसे अपेक्षाकृत सुरक्षित माना जा सकता है। अभिगम नियंत्रण मॉडल परिमाण के कई आदेशों से अधिक जटिल है।

अभिगम नियंत्रण मॉडल विशेषाधिकार प्रदान करने के लिए एक्सेस कंट्रोल सूचियों (एसीएल) का उपयोग करता है। विशेषाधिकार केवल आवश्यक विशेषाधिकारों के साथ एक प्रक्रिया द्वारा प्रदान किया जा सकता है। यह मॉडल न केवल उपयोगकर्ता, समूह और अन्य के नियंत्रण को पढ़ने, लिखने और निष्पादित करने की अनुमति देता है, बल्कि यह नेटवर्क पर और विंडोज डोमेन के बीच फ़ाइलों को नियंत्रित करने की अनुमति देता है। (आप पीएएम के साथ यूनिक्स सिस्टम पर पागलपन का स्तर भी प्राप्त कर सकते हैं।)

नोट: एक्सेस कंट्रोल मॉडल केवल एनटीएफएस विभाजन पर उपलब्ध है, यदि आप एफओटी विभाजन का उपयोग कर रहे हैं तो आप एसओएल हैं।

एसीएल का उपयोग गधे में एक बड़ा दर्द है। यह एक मामूली उपक्रम नहीं है और इसके लिए आपको केवल एसीएल नहीं सीखना होगा, बल्कि सुरक्षा डिस्क्रिप्टर, एक्सेस टोकन और अन्य सभी उन्नत विंडोज सुरक्षा अवधारणाओं के बारे में भी सीखना होगा।

सौभाग्य से मेरे लिए, मेरी वर्तमान जरूरतों के लिए, मुझे वास्तविक सुरक्षा की आवश्यकता नहीं है जो एक्सेस कंट्रोल मॉडल प्रदान करता है। मैं मूल रूप से विंडोज़ पर अनुमतियों को सेट करने का नाटक कर सकता हूं, जब तक कि मैं वास्तव में लिनक्स पर अनुमतियां सेट करता हूं।

विंडोज़ का समर्थन करता है जिसे वे "आईएसओ सी ++ अनुरूप" संस्करण को chmod (2) कहते हैं। इस एपीआई को _chmod कहा जाता है, और यह chmod (2) के समान है, लेकिन अधिक सीमित है और टाइप या नाम संगत (बिल्कुल नहीं)। विंडोज़ में एक बहिष्कृत chmod भी है, इसलिए आप आसानी से विंडोज़ में chmod नहीं जोड़ सकते हैं और लिनक्स पर सीधे chmod (2) का उपयोग कर सकते हैं।

#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 

यह याद रखना महत्वपूर्ण है कि मेरे समाधान केवल डॉस प्रकार सुरक्षा प्रदान करता है महत्वपूर्ण है:

मैं निम्नलिखित लिखा था। इसे कोई सुरक्षा के रूप में भी जाना जाता है, लेकिन यह सुरक्षा की मात्रा है जो अधिकांश ऐप्स आपको विंडोज पर देते हैं।

इसके अलावा, मेरे समाधान के तहत, यदि आप समूह या अन्य (या उस मामले के लिए इसे हटाने) की अनुमति देते हैं, तो आप STRICT_UGO_PERMISSIONS को परिभाषित नहीं करते हैं, तो आप वास्तव में स्वामी को बदल रहे हैं। यदि आप ऐसा नहीं करना चाहते थे, लेकिन आपको अभी भी पूर्ण विंडोज एसीएल अनुमतियों की आवश्यकता नहीं है, तो बस STRICT_UGO_PERMISSIONS को परिभाषित करें।

8

ऐसा करने के लिए कोई क्रॉस-प्लेटफार्म तरीका नहीं है। विंडोज यूनिक्स-शैली फ़ाइल अनुमतियों का समर्थन नहीं करता है। जो भी आप चाहते हैं उसे करने के लिए, आपको उस फ़ाइल के लिए एक्सेस कंट्रोल सूची बनाने की आवश्यकता होगी, जो आपको उपयोगकर्ताओं और समूहों के लिए एक्सेस अनुमतियों को स्पष्ट रूप से परिभाषित करने देगी।

एक निर्देशिका में फ़ाइल बनाने का एक विकल्प हो सकता है जिसकी सुरक्षा सेटिंग्स पहले से ही सभी को छोड़कर उपयोगकर्ता को बाहर कर दी गई है।

+0

वह उत्तर कुछ लोगों को वास्तव में इसके बारे में सोचना चाहिए: क्या ऐप्स में अनुमतियों के साथ वास्तव में आवश्यक है? कई में, कई मामलों में यह चीजें तोड़ती नहीं है और यहां तक ​​कि तोड़ती है, क्योंकि यह प्रवेशकर्ताओं और उपयोगकर्ताओं को फिट होने पर अनुमतियों को नियंत्रित करने की संभावना लेती है। खासकर उदा। विंडोज़ पर, कोई अन्य उपयोगकर्ता डिफ़ॉल्ट रूप से उपयोगकर्ता के घर डीआईआर तक पहुंचने में सक्षम नहीं है, इसलिए फ़ाइलों को "निजी" मैन्युअल रूप से बनाने की आवश्यकता नहीं है। लिनक्स ऐप्स में बहुत सी chmod + umask-हैंडलिंग एसीएल, उचित विरासत और इस तरह की कमी की वजह से विरासत है। जितना संभव हो उससे बचने की कोशिश करें। –

1

कोई विचार नहीं है कि यह काम करेगा, लेकिन आप chmod.exe निष्पादन योग्य का उपयोग कर सकते हैं जो सिगविन के साथ आता है।

+0

+1 क्योंकि यह एक दिलचस्प विचार है। मुझे पता है कि साइगविन के तहत chmod हर बार मैंने कभी कोशिश की है सही चीज करता है। – rmeador

+0

क्या? यह एनटीएफएस एसीएल बदलता है? – aib

1

सी ++ में ऐसा करने का कोई मानक तरीका नहीं है, लेकिन इस विशेष आवश्यकता के लिए आपको शायद #ifdef _WIN32 के साथ एक कस्टम रैपर लिखना चाहिए। क्यूटी के पास QFile कक्षा में एक अनुमति रैपर है, लेकिन यह निश्चित रूप से क्यूटी के आधार पर होगा ...

+0

आपके द्वारा प्रदान किए गए लिंक पर चेतावनी का तात्पर्य यह है कि यह विंडोज पर अपेक्षित काम नहीं कर सकता है। – Ferruccio

0

आप इसे क्रॉस-प्लेटफ़ॉर्म तरीके से नहीं कर सकते हैं। लिनक्स में, आपको एक नया खोल बनाने के लिए system(2) का उपयोग करने के बजाय chmod(2) फ़ंक्शन का उपयोग करना चाहिए। विंडोज़ पर, आपको उचित अनुमतियों के साथ एक एसीएल (एक्सेस-कंट्रोल सूची) बनाने के लिए विभिन्न authorization functions का उपयोग करना होगा।

3

system() कॉल एक अजीब जानवर है। मुझे मैक पर कई एनओएनएस पर एक एनओपी सिस्टम() कार्यान्वयन द्वारा काट दिया गया है। यह कार्यान्वयन परिभाषित किया गया है कि मानक परिभाषित नहीं करता है कि एक कार्यान्वयन (प्लेटफॉर्म/कंपाइलर) क्या करना है। दुर्भाग्यवश, यह आपके फ़ंक्शन के दायरे से बाहर कुछ करने का एकमात्र मानक तरीका है (आपके मामले में - अनुमतियों को बदलना)।

अद्यतन: एक हैक प्रस्तावित:

  • आपके सिस्टम पर उपयुक्त अनुमतियों वाले एक गैर खाली फ़ाइल बनाएँ।
  • इस फ़ाइल को अपने वांछित आउटपुट में कॉपी करने के लिए बूस्ट फाइल सिस्टम के copy_file का उपयोग करें।

    void copy_file(const path& frompath, const path& topath): सेपथ द्वारा संदर्भित फ़ाइल की सामग्री और विशेषताओं को शीर्ष पर संदर्भित फ़ाइल में कॉपी किया गया है। यह दिनचर्या एक गंतव्य फ़ाइल अनुपस्थित होने की अपेक्षा करता है; यदि गंतव्य फ़ाइल मौजूद है, तो यह एक अपवाद फेंकता है। इसलिए, यह यूनिक्स में निर्दिष्ट निर्दिष्ट सीपी कमांड के बराबर नहीं है। यह भी उम्मीद की जाती है कि सेपैथ वैरिएबल एक उचित नियमित फ़ाइल का संदर्भ देगा। इस उदाहरण पर विचार करें: सेपथ एक प्रतीकात्मक लिंक/tmp/file1 को संदर्भित करता है, जो बदले में एक फ़ाइल/tmp/file2 को संदर्भित करता है; टॉपथ है, कहें,/tmp/file3। इस स्थिति में, copy_file विफल हो जाएगी। यह एक और अंतर है कि यह एपीआई खेल सीपी कमांड की तुलना में।

  • अब, वास्तविक सामग्री के साथ आउटपुट को ओवरराइट करें।

लेकिन, यह केवल एक हैक है जिसे मैंने मध्यरात्रि के बाद लंबे समय तक सोचा था। इसे नमक के चुटकी से लें और इसे आजमाएं :)

1

मुझे विंडोज कमांड लाइन से आसानी से chmod 700 करने के कुछ तरीके मिले। मैं एक और सवाल पोस्ट करने जा रहा हूं जिसमें उपयोग करने के लिए समकक्ष Win32 सुरक्षा डिस्क्रिप्टर संरचना के साथ आने वाली सहायता के लिए पूछना है (यदि मैं इसे अगले कुछ घंटों में नहीं समझ सकता)।

Windows 2000 & XP (messy- यह हमेशा संकेत करने के लिए लगता है): यदि आप की क्षमता पड़ा

:

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

विंडोज 2003+:

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

संपादित करें एटीएल का उपयोग करें, इस आलेख में यह शामिल है (मेरे पास विजुअल स्टूडियो उपलब्ध नहीं है): http://www.codeproject.com/KB/winsdk/accessctrl2.aspx

वास्तव में, यह नमूना कोड के रूप में अच्छी तरह से यह कुछ है कि आप के लिए काम करता है होना चाहिए गैर ATL नमूना कोड भी शामिल है का कहना है (और मुझे!)

यह ध्यान रखना होगा प्राप्त करने के लिए आर/डब्ल्यू है/x केवल Win32 पर मालिक के लिए, आपको बस फ़ाइल से सभी सुरक्षा वर्णनकर्ताओं को मिटा देना होगा और पूर्ण नियंत्रण के साथ अपने लिए एक जोड़ना होगा।

2

सी ++ 17 और उसके std::filesystem वाली फ़ाइल के लिए 0700 सेट करने के लिए क्रॉस-प्लेटफ़ॉर्म उदाहरण।

#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. 
    }   
} 

std::filesystem::permissions, std::filesystem::perms और std::filesystem::perm_options देखें।

संबंधित मुद्दे