学习笔记
修改程序,用于判断文件类型
$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需要掌握 文件大小 文件类型 符号穿透