简体   繁体   中英

flags for st_mode of stat system call

I'm trying to understand the flags for the st_mode field of the stat structure of that stat command, but I'm having such a hard time! I found this example here , but I really don't understand this code fragment:

if ( mode & S_IRUSR ) str[1] = 'r';    /* 3 bits for user  */
if ( mode & S_IWUSR ) str[2] = 'w';
if ( mode & S_IXUSR ) str[3] = 'x';

if ( mode & S_IRGRP ) str[4] = 'r';    /* 3 bits for group */
if ( mode & S_IWGRP ) str[5] = 'w';
if ( mode & S_IXGRP ) str[6] = 'x';

if ( mode & S_IROTH ) str[7] = 'r';    /* 3 bits for other */
if ( mode & S_IWOTH ) str[8] = 'w';
if ( mode & S_IXOTH ) str[9] = 'x';

I know that "&" is the bitwise AND operator, but nothing else. I don't even know what to ask.

PD: Sorry about the previous questions I asked. I don't know how to mark a question answered or anything like that:(

mode is a bitfield which is a common way to pack data. Think of each bit in the field as being a toggle switch which can be set to off or on. To check if the toggle is on, you check to see if the appropriate bit has been set using the & operator. You can set bits using |and clear them using ~ bitwise operations .

Well, the POSIX spec for <sys/stat.h> enumerates everything you can learn from the st_mode field of struct stat .

Is your question "What can this field tell me", or is it "How do I extract the information", or both?

It's common in operating system programing to use unsigned integers to hold a series of bits that describe something. In this case, mode has 9 bits of interest. One bit tells if the owner can read, one for owner write, one for owner execute, and similar bits for the group and others. The trick is in extracting whether a bit is set or not.

Here's an example. The S_IRUSR is a name for a bitmask that describes the "owner read" bit. It's defined in the specs as 0400 (octal) which translates to 100000000 in binary. When you take the binary and of this value with the mask, you get the value 100000000 (binary) if the 9th bit of the mask is set. Otherwise you get 0.

The if-statement evaluates to true if the large value is returned, and false otherwise. This way if the bit is set, 'r' is written into the string into position 1. The same technique applies to all of the other bits as well.

As a 'newbie' I came across this question.

My first step was 'man 2 stat'.(before here)

In there you will find this informative piece of example code

    EXAMPLE from 'man 2 stat'

    The following program calls lstat() and displays selected fields in the returned stat 
    structure.

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/sysmacros.h>

    int
    main(int argc, char *argv[])
    {
    struct stat sb;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (lstat(argv[1], &sb) == -1) {
        perror("lstat");
        exit(EXIT_FAILURE);
    }

    printf("ID of containing device:  [%lx,%lx]\n",
            (long) major(sb.st_dev), (long) minor(sb.st_dev));
    printf("File type:                ");

    switch (sb.st_mode & S_IFMT) {
       case S_IFBLK:  printf("block device\n");            break;
       case S_IFCHR:  printf("character device\n");        break;
       case S_IFDIR:  printf("directory\n");               break;
       case S_IFIFO:  printf("FIFO/pipe\n");               break;
       case S_IFLNK:  printf("symlink\n");                 break;
       case S_IFREG:  printf("regular file\n");            break;
       case S_IFSOCK: printf("socket\n");                  break;
       default:       printf("unknown?\n");                break;
    }
    printf("I-node number:            %ld\n", (long) sb.st_ino);
    printf("Mode:                     %lo (octal)\n",
           (unsigned long) sb.st_mode);
    printf("Link count:               %ld\n", (long) sb.st_nlink);
    printf("Ownership:                UID=%ld   GID=%ld\n",
           (long) sb.st_uid, (long) sb.st_gid);

    printf("Preferred I/O block size: %ld bytes\n",
           (long) sb.st_blksize);
    printf("File size:                %lld bytes\n",
           (long long) sb.st_size);
    printf("Blocks allocated:         %lld\n",
            (long long) sb.st_blocks);
    printf("Last status change:       %s", ctime(&sb.st_ctime));
    printf("Last file access:         %s", ctime(&sb.st_atime));
    printf("Last file modification:   %s", ctime(&sb.st_mtime));

    exit(EXIT_SUCCESS);
   }

As remarked above by others, this uses a bitmask in 'switch (sb.st_mode & S_IFMT)'. It seems, most of the plumbing work is done already for us. I did, however, find that when compiling under 'gcc' these bitmask defines used leading underscores.

i,e. 'switch (sb.st_mode & __S_IFMT )'

Not being very experienced, I guess this detail may vary across versions.

I found it to be a good starting point (along with the rest of the man content for stat) (An additional observation for those trying this on Windows Subsystem for Linux. You might get strange results occasionally; ;-) )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM