Linux系统编程 50 -stat和stat函数 穿透和非穿透

学习笔记
修改程序,用于判断文件类型

$cat mystat.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
    struct stat sbuf;
    int ret = stat(argv[1],&sbuf);
    if( -1 == ret )
    {
        perror("stat error");
        exit(1);
    }

//    printf("file size:%ld\n",sbuf.st_size);

    if(S_ISREG(sbuf.st_mode))
    {
        printf("it is a regular\n");
    }
    else if (S_ISDIR(sbuf.st_mode))
    {
        printf("it is a dictory!\n");
    }
    else if(S_ISFIFO(sbuf.st_mode))
    {
        printf("it is a pipe\n");
    }
    else if(S_ISLNK(sbuf.st_mode))
    {
        printf("it is a sym link\n");
    }
    return 0;
}

makefile 文件为

$cat makefile 
src=$(wildcard ./*.c) 
target=$(patsubst %.c,%,$(src)) 
myArgs= -Wall -g
All:${target}
%:%.c
    gcc  $< -o $@ $(myArgs)
clean:
    -rm -rf $(target) a.out 
.PHONY: clean All


make下

make mystat
gcc  mystat.c -o mystat -Wall -g

普通文件

$./mystat f.c
it is a regular


文件夹

$mkdir newdir
$./mystat newdir
it is a dictory!

管道文件

$mkfifo myfifo
$./mystat myfifo 
it is a pipe

软链接

$ln -s f.c f.soft
$ll
total 48
drwxrwxr-x 3 ubuntu ubuntu  4096 12月 24 20:47 ./
drwxrwxr-x 9 ubuntu ubuntu  4096 12月 24 20:15 ../
-rwxr--r-- 1 ubuntu ubuntu   500 12月 24 20:15 f.c*
lrwxrwxrwx 1 ubuntu ubuntu     3 12月 24 20:47 f.soft -> f.c*
-rwxr--r-- 1 ubuntu ubuntu   178 12月 24 20:15 makefile*
prw-rw-r-- 1 ubuntu ubuntu     0 12月 24 20:46 myfifo|
-rwxrwxr-x 1 ubuntu ubuntu 20560 12月 24 20:45 mystat*
-rw-rw-r-- 1 ubuntu ubuntu   600 12月 24 20:45 mystat.c
drwxrwxr-x 2 ubuntu ubuntu  4096 12月 24 20:45 newdir/

$./mystat f.soft 
it is a regular


提示软链接是普通文件!!!
也可以个目录创建软链接(但是不能给目录创建硬链接)

$ln -s newdir newdir.soft
$ls
f.c  f.soft  makefile  myfifo  mystat  mystat.c  newdir  newdir.soft
$ll
total 48
drwxrwxr-x 3 ubuntu ubuntu  4096 12月 24 20:53 ./
drwxrwxr-x 9 ubuntu ubuntu  4096 12月 24 20:15 ../
-rwxr--r-- 1 ubuntu ubuntu   500 12月 24 20:15 f.c*
lrwxrwxrwx 1 ubuntu ubuntu     3 12月 24 20:47 f.soft -> f.c*
-rwxr--r-- 1 ubuntu ubuntu   178 12月 24 20:15 makefile*
prw-rw-r-- 1 ubuntu ubuntu     0 12月 24 20:46 myfifo|
-rwxrwxr-x 1 ubuntu ubuntu 20560 12月 24 20:45 mystat*
-rw-rw-r-- 1 ubuntu ubuntu   600 12月 24 20:45 mystat.c
drwxrwxr-x 2 ubuntu ubuntu  4096 12月 24 20:45 newdir/
lrwxrwxrwx 1 ubuntu ubuntu     6 12月 24 20:53 newdir.soft -> newdir/
$./mystat newdir.soft
it is a dictory!

也同样提示目录的软链接是文件夹!!!

为什么没有提示是链接呢?
问题出在stat身上。

这种现象称之为stat穿透(穿透符号链接),

不想穿透的话,使用lstat函数(不会穿透符号链接)

修改程序:

$cat mylstat.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
    struct stat sbuf;
    int ret =lstat(argv[1],&sbuf);
    if( -1 == ret )
    {
        perror("stat error");
        exit(1);
    }

//    printf("file size:%ld\n",sbuf.st_size);

    if(S_ISREG(sbuf.st_mode))
    {
        printf("it is a regular\n");
    }
    else if (S_ISDIR(sbuf.st_mode))
    {
        printf("it is a dictory!\n");
    }
    else if(S_ISFIFO(sbuf.st_mode))
    {
        printf("it is a pipe\n");
    }
    else if(S_ISLNK(sbuf.st_mode))
    {
        printf("it is a sym link\n");
    }
    return 0;
}
$make mylstat
gcc  mylstat.c -o mylstat -Wall -g
$./mylstat newdir.soft
it is a sym link
$./mylstat f.soft 
it is a sym link


穿透和不穿透

$ls -l f.soft
lrwxrwxrwx 1 ubuntu ubuntu 3 12月 24 20:47 f.soft -> f.c

这里面的3 代表 f.c文件名的长度
ls -l 不穿透符号链接

$cat f.c
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112a$
$cat f.soft
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112a$


所以cat 穿透符号链接,看到本尊(f.c)。


获取文件的大小:sbuf.st_size
获取文件的类型:sbuf.st_mode
获取文件的权限:sbuf.st_mode


man 查看函数说明的时候,对应重要的函数
一般会有demo,使用G,就可以调到demo那里

#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);
}

问题:如何查看 man中 宏定义的具体指 比如 S_IFMT


我的方法(自己发现):
1.在查stat的系统调用

man 2 stat

2.查看具体成员

st_mode
       This field contains the file type and mode.  See inode(7) for further information.


       
3. 根据提示inode(7)
在shell中,输入

man 7 inode

S_IFMT     0170000   bit mask for the file type bit field

S_IFSOCK   0140000   socket
S_IFLNK    0120000   symbolic link
S_IFREG    0100000   regular file
S_IFBLK    0060000   block device
S_IFDIR    0040000   directory
S_IFCHR    0020000   character device
S_IFIFO    0010000   FIFO

S_ISUID     04000   set-user-ID bit (see execve(2))
S_ISGID     02000   set-group-ID bit (see below)
S_ISVTX     01000   sticky bit (see below)

S_IRWXU     00700   owner has read, write, and execute permission
S_IRUSR     00400   owner has read permission
S_IWUSR     00200   owner has write permission
S_IXUSR     00100   owner has execute permission

S_IRWXG     00070   group has read, write, and execute permission
S_IRGRP     00040   group has read permission
S_IWGRP     00020   group has write permission
S_IXGRP     00010   group has execute permission

S_IRWXO     00007   others  (not  in group) have read, write, and
                    execute permission
S_IROTH     00004   others have read permission
S_IWOTH     00002   others have write permission
S_IXOTH     00001   others have execute permission


S_IFMT     就是位掩码

 
文件类型加上未知,总共8种。

特殊权限的最后一位叫做黏着位。


对应stat/lstat需要掌握 文件大小 文件类型 符号穿透

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值