सी

2012-04-25 6 views
14

में स्टेट (2) का उपयोग करके 'ls -l' जैसे प्रिंटिंग फ़ाइल अनुमतियां मैं एक छोटा सी प्रोग्राम लिखने की कोशिश कर रहा हूं जो यूनिक्स कमांड ls -l का अनुकरण करता है। ऐसा करने के लिए, मैं stat(2) सिस्कल का उपयोग कर रहा हूं और अनुमतियों को लिखने के लिए एक छोटे से हिचकी में भाग गया हूं। मेरे पास mode_t वैरिएबल है जिसमें st_mode से फ़ाइल अनुमतियां हैं, और उस मान को स्ट्रिंग प्रस्तुति में पार्स करना मुश्किल नहीं होगा, लेकिन मैं बस सोच रहा था कि इससे ऐसा करने का बेहतर तरीका है या नहीं। गूगल सेसी

उत्तर

40

उदाहरण

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

int main(int argc, char **argv) 
{ 
    if(argc != 2)  
     return 1; 

    struct stat fileStat; 
    if(stat(argv[1],&fileStat) < 0)  
     return 1; 

    printf("Information for %s\n",argv[1]); 
    printf("---------------------------\n"); 
    printf("File Size: \t\t%d bytes\n",fileStat.st_size); 
    printf("Number of Links: \t%d\n",fileStat.st_nlink); 
    printf("File inode: \t\t%d\n",fileStat.st_ino); 

    printf("File Permissions: \t"); 
    printf((S_ISDIR(fileStat.st_mode)) ? "d" : "-"); 
    printf((fileStat.st_mode & S_IRUSR) ? "r" : "-"); 
    printf((fileStat.st_mode & S_IWUSR) ? "w" : "-"); 
    printf((fileStat.st_mode & S_IXUSR) ? "x" : "-"); 
    printf((fileStat.st_mode & S_IRGRP) ? "r" : "-"); 
    printf((fileStat.st_mode & S_IWGRP) ? "w" : "-"); 
    printf((fileStat.st_mode & S_IXGRP) ? "x" : "-"); 
    printf((fileStat.st_mode & S_IROTH) ? "r" : "-"); 
    printf((fileStat.st_mode & S_IWOTH) ? "w" : "-"); 
    printf((fileStat.st_mode & S_IXOTH) ? "x" : "-"); 
    printf("\n\n"); 

    printf("The file %s a symbolic link\n", (S_ISLNK(fileStat.st_mode)) ? "is" : "is not"); 

    return 0; 
} 

परिणाम:

Information for 2.c 
--------------------------- 
File Size:    1223 bytes 
Number of Links:  1 
File inode:    39977236 
File Permissions:  -rw-r--r-- 

The file is not a symbolic link
+1

उत्तर के लिए धन्यवाद। इससे एक टन मदद मिली है। – cheezone

+2

ध्यान दें कि कोड 'lstat()' के बजाय 'stat()' का उपयोग करता है, सिमलिंक टूटा हुआ होने पर केवल 'symlink' की रिपोर्ट करने का एकमात्र समय होता है। अन्यथा, यह symlink के अंत में फ़ाइल पर रिपोर्ट करेगा। –

14

मूल बातें काफी सरल कर रहे हैं; मुश्किल बिट्स SUID और एसजीआईडी ​​बिट्स और चिपचिपा बिट हैं, जो 'एक्स' बिट्स को संशोधित करते हैं। उपयोगकर्ता, समूह, मालिक के लिए 3 ऑक्टल अंकों में अनुमतियों को विभाजित करने और उन लोगों का उपयोग करके 3-वर्ण स्ट्रिंग्स जैसे rwx और --- में अनुक्रमित करने पर विचार करें। फिर अन्य मोड बिट्स के आधार पर उचित x बिट्स समायोजित करें। फ़ाइल प्रकार को अलग से निपटाया जाना होगा, लेकिन आप 16 संभावित मानों (संभवतः मास्किंग के साथ) और 16 प्रविष्टि तालिका का उपयोग 16 संभावित मानों से निपटने के लिए कर सकते हैं (जिनमें से सभी किसी दिए गए सिस्टम पर मान्य नहीं हैं) । या आप नीचे दिए गए कोड में दिखाए गए ज्ञात प्रकारों से निपट सकते हैं।

+----+---+---+---+---+ 
|type|SSS|USR|GRP|OTH| 
+----+---+---+---+---+ 

4 प्रकार बिट्स, तीन एस बिट्स (setuid, setgid, चिपचिपा) और उपयोगकर्ता, समूह और अन्य बिट्स।

यह कोड मैं mode_t को एक स्ट्रिंग में परिवर्तित करने के लिए उपयोग करता हूं। यह एक अच्छी तरह से थ्रेडलेस प्रोग्राम के लिए लिखा गया था, इसलिए यह स्थिर डेटा का उपयोग करता है; इसे संशोधित करने के लिए एक इनपुट पैरामीटर के रूप में उत्पादन स्ट्रिंग लेने के लिए तुच्छ होगा:

/* Convert a mode field into "ls -l" type perms field. */ 
static char *lsperms(int mode) 
{ 
    static const char *rwx[] = {"---", "--x", "-w-", "-wx", 
    "r--", "r-x", "rw-", "rwx"}; 
    static char bits[11]; 

    bits[0] = filetypeletter(mode); 
    strcpy(&bits[1], rwx[(mode >> 6)& 7]); 
    strcpy(&bits[4], rwx[(mode >> 3)& 7]); 
    strcpy(&bits[7], rwx[(mode & 7)]); 
    if (mode & S_ISUID) 
     bits[3] = (mode & S_IXUSR) ? 's' : 'S'; 
    if (mode & S_ISGID) 
     bits[6] = (mode & S_IXGRP) ? 's' : 'l'; 
    if (mode & S_ISVTX) 
     bits[9] = (mode & S_IXOTH) ? 't' : 'T'; 
    bits[10] = '\0'; 
    return(bits); 
} 

static int filetypeletter(int mode) 
{ 
    char c; 

    if (S_ISREG(mode)) 
     c = '-'; 
    else if (S_ISDIR(mode)) 
     c = 'd'; 
    else if (S_ISBLK(mode)) 
     c = 'b'; 
    else if (S_ISCHR(mode)) 
     c = 'c'; 
#ifdef S_ISFIFO 
    else if (S_ISFIFO(mode)) 
     c = 'p'; 
#endif /* S_ISFIFO */ 
#ifdef S_ISLNK 
    else if (S_ISLNK(mode)) 
     c = 'l'; 
#endif /* S_ISLNK */ 
#ifdef S_ISSOCK 
    else if (S_ISSOCK(mode)) 
     c = 's'; 
#endif /* S_ISSOCK */ 
#ifdef S_ISDOOR 
    /* Solaris 2.6, etc. */ 
    else if (S_ISDOOR(mode)) 
     c = 'D'; 
#endif /* S_ISDOOR */ 
    else 
    { 
     /* Unknown type -- possibly a regular file? */ 
     c = '?'; 
    } 
    return(c); 
} 
+0

आपके उत्तर द्वारा प्रदान की गई गहराई की सराहना करें! प्रति दिन कुछ नया सीखें! – cheezone

+0

क्लैंग '' -वेरथिंग' 'काफी सही शिकायत की गई है :) –

+0

@ अरनन कुडबार्ड-बेल: मैं' क्लैंग-वेवथिंग 'के समान कुछ के साथ आदेशों का एक कॉर्पस साफ़ कर रहा हूं और यह कभी-कभी थोड़ा दर्दनाक हो सकता है। मैंने वास्तव में 'clang -Weverything' सीधे कोशिश नहीं की है; मेरे द्वारा उपयोग किए जा रहे विकल्पों की तुलना में यह कम कठिन हो सकता है (लगभग 18 '-W *' झंडे; '-वोनवर्जन' मेरे कोड के लिए परेशानी का सबसे बड़ा कारण है)। –

0

मैं if/ else if वाक्य रचना पसंद नहीं है।

मैं switch कथन का उपयोग करना पसंद करता हूं। थोड़ा मैं जिस तरह से हम अलग मैक्रो का उपयोग कर ऐसा कर सकते हैं पाया संघर्ष उदाहरण के लिए के बाद:

S_ISCHR (mode) 

बराबर है करने के लिए:

((mode & S_IFMT) == S_IFCHR) 

यह हमें इस तरह एक स्विच बयान का निर्माण करने की अनुमति देता है:

char f_type(mode_t mode) 
{ 
    char c; 

    switch (mode & S_IFMT) 
    { 
    case S_IFBLK: 
     c = 'b'; 
     break; 
    case S_IFCHR: 
     c = 'c'; 
     break; 
    case S_IFDIR: 
     c = 'd'; 
     break; 
    case S_IFIFO: 
     c = 'p'; 
     break; 
    case S_IFLNK: 
     c = 'l'; 
     break; 
    case S_IFREG: 
     c = '-'; 
     break; 
    case S_IFSOCK: 
     c = 's'; 
     break; 
    default: 
     c = '?'; 
     break; 
    } 
    return (c); 
} 

मेरी राय में यह if/else if दृष्टिकोण से थोड़ा अधिक सुरुचिपूर्ण है।

+0

क्या आपने यह निर्धारित करने के लिए असेंबली कोड डाला है कि कौन सा अधिक कुशल है? (उदा। 'gcc -S -masm = intel -O2 -o filemode.asm filemode.c') –