学习笔记
修改程序,用于判断文件类型
$cat mystat.c #include#include #include #include #include #include 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:%ldn",sbuf.st_size); if(S_ISREG(sbuf.st_mode)) { printf("it is a regularn"); } else if (S_ISDIR(sbuf.st_mode)) { printf("it is a dictory!n"); } else if(S_ISFIFO(sbuf.st_mode)) { printf("it is a pipen"); } else if(S_ISLNK(sbuf.st_mode)) { printf("it is a sym linkn"); } 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#include #include #include #include #include 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:%ldn",sbuf.st_size); if(S_ISREG(sbuf.st_mode)) { printf("it is a regularn"); } else if (S_ISDIR(sbuf.st_mode)) { printf("it is a dictory!n"); } else if(S_ISFIFO(sbuf.st_mode)) { printf("it is a pipen"); } else if(S_ISLNK(sbuf.st_mode)) { printf("it is a sym linkn"); } 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#include #include #include #include #include int main(int argc, char *argv[]) { struct stat sb; if (argc != 2) { fprintf(stderr, "Usage: %s 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 devicen"); break; case S_IFCHR: printf("character devicen"); break; case S_IFDIR: printf("directoryn"); break; case S_IFIFO: printf("FIFO/pipen"); break; case S_IFLNK: printf("symlinkn"); break; case S_IFREG: printf("regular filen"); break; case S_IFSOCK: printf("socketn"); break; default: printf("unknown?n"); break; } printf("I-node number: %ldn", (long) sb.st_ino); printf("Mode: %lo (octal)n", (unsigned long) sb.st_mode); printf("link count: %ldn", (long) sb.st_nlink); printf("Ownership: UID=%ld GID=%ldn", (long) sb.st_uid, (long) sb.st_gid); printf("Preferred I/O block size: %ld bytesn", (long) sb.st_blksize); printf("File size: %lld bytesn", (long long) sb.st_size); printf("Blocks allocated: %lldn", (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需要掌握 文件大小 文件类型 符号穿透



