《UNIX环境高级编程》笔记 第四章——文件和目录

1. 简介

存储在文件系统中的每一个文件,它们都有自己的文件类型,所有者,访问权限,链接数、大小等属性。本章函数可以对文件或目录的属性进行访问和修改,对于更多的细节,可以查看相关函数的man手册。

2. 函数原型

1. int stat(const char *pathname, struct stat *statbuf);
2. int fstat(int fd, struct stat *statbuf);
3. int lstat(const char *pathname, struct stat *statbuf);

4. int fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags);

返回文件(目录)的属性:

(1)lstat返回符号链接本身的信息,而不是符号链接引用的文件信息。

(2)fstatatf以打开目录的文件描述符dirfd为起始目录,返回相对路径pathname的文件信息,如果pathname是绝对路径,则忽略dirfd。flags指定是否跟随符号链接。

4个函数返回值:若成功,返回0;若出错,返回-1

1. int access(const char *pathname, int mode)

2. int faccessat(int fd, const char *pathname, int mode, int flag)

测试文件的访问权限,mode参数:

F_OK:测试文件是否存在

R_OK:测试读权限

W_OK:测试写权限

 X_OK:测试执行权限

若flag=AT_EACCESS,则访问检测用的是有效用户ID和有效组ID,而不是实际用户ID和实际组ID

2个函数返回值:若成功,返回0;若出错,返回-1

mode_t umask(mode_t cmask)

设置文件模式创建屏蔽字

返回值:返回之前的文件模式创建屏蔽字

1. int chmod(const char *pathname, mode_t mode)

2. int fchmod(int fd, mode_t mode)

3. int fchmodat(int fd, const char *pathname, mode_t mode, int flag)

3个函数改变现有文件的访问权限:

若flag=AT_SYMLINK_NOFOLLOW,fchmodat不跟随符号链接

3个函数返回值:若成功,返回0;若出错,返回-1

1. int chown(const char *pathanme, uid_t owner, gid_t group)

2. int fchown(int fd, uid_t owner, gid_t group)

3. int fchownat(int fd, const char *pathanme, uid_t owner, gid_t group, int flag)

4. int lchown(const char *pathanme, uid_t owner, gid_t group)

4个函数更改文件的用户ID和组ID,若owner或group中任一个是-1,则对应ID不变。当pathname为相对路径时,若fchownat函数flag=AT_SYMLINK_NOFOLLOW,则与lchown作用一样,只修改符号链接本身,而不是符号链接引用的文件。

4个函数返回值:若成功,返回0;若出错,返回-1

1. int truncate(const char *pathname, off_t lenth)

2. int ftruncate(const char *pathname, off_t lenth)

截断文件长度

2个函数返回值:若成功,返回0;若出错,返回-1

1. int link(const char *existingpath, const char *newpath)

2. int linkat(int efd, const char *existingpath, int nfd, const char *newpath, int flag)

建立文件硬链接,不允许对目录建立硬链接

2个函数返回值:若成功,返回0;若出错,返回-1

1. int ulink(const char *pathname)

2. int ulinkat(int fd, const char *pathname, int flag)

解除文件链接,当链接计数为0时,文件内容被删除,另一个条件是当进程打开了一个文件,即使该文件链接计数为0,也不能删除其内容。当flag=AT_REMOVEDIR时,可删除目录。

2个函数返回值:若成功,返回0;若出错,返回-1

int remove(const char *pathname)

解除对文件或目录的链接

返回值:若成功,返回0;若出错,返回-1

1. int rename(const char *oldname, const char *newname)

2. int renameat(int oldfd, const char *oldname, int newfd, const char *newname)

重命名文件或目录

2个函数返回值:若成功,返回0;若出错,返回-1

1. int symlink(const char *actualpath, const char *sympath)

2. int symlinkat(const char *actualpath, int fd, const char *sympath)

创建一个符号链接

2个函数返回值:若成功,返回0;若出错,返回-1

1. ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t bufsize)

2. ssize_t readlink(int fd, const char *restrict pathname, char *restrict buf, size_t bufsize)

读取符号链接文件本身的内容

2个函数返回值:若成功,返回读取的字节数;若出错,返回-1

1. int futimens(int fd, const struct timespec times[2])

2. int utimensat(int fd, const char *path,  const struct timespec times[2], int flag)

3. int utimes( const struct timeval times[2])

更改文件的访问和修改时间

3个函数返回值:若成功,返回读取的字节数;若出错,返回-1

1. int mkdir(const char *pathname, mode_t mod)

2. int mkdirat(int fd, const char *pathname, mode_t mod)

创建一个目录

2个函数返回值:若成功,返回0;若出错,返回-1

int rmdir(const char *pathname)

删除一个空目录

返回值:若成功,返回0;若出错,返回-1

DIR *opendir(const char *pathname)

DIR *fdopendir(int fd)

打开目录

2个函数返回值:若成功,返回指针;若出错,返回NULL

struct dirent *readdir(DIR *dp)

读取一个目录项

返回值:若成功,返回指针;若出错,返回NULL

void rewinddir(DIR *dp)将目录项的位置重置为开始
int closedir(DIR *dp)

关闭目录

返回值:若成功,返回指针;若出错,返回-1

long telldir(DIR *dp)返回值:若成功,返回与dp关联的目录中的当前位置;若出错,返回-1
void seekdir(DIR *dp, long loc)设置目录流的位置

1. int chdir(const char *name)

2. int fchdir(int fd)

更改当前工作目录

2个函数返回值:若成功,返回0;若出错,返回-1

char *getcwd(char *buf, size_t size)

返回调用进程当前工作目录

返回值:若成功,返回buf;若出错,返回NULL

3.实例

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

#define TESET_ACCESS(mode, bit) do { \
	if ((mode)&bit) { \
		printf( #bit " is ok\n"); \
	} else { \
		printf( #bit " is not\n"); \
	} \
} while (0)

void printf_stat(const char *file, const struct stat *buf)
{
	printf("file %s stat: \n", file);

	/* // man 7 inode
	S_ISREG(m)	is it a regular file?
	S_ISDIR(m)  directory?
	S_ISCHR(m)  character device?
	S_ISBLK(m)  block device?
	S_ISFIFO(m) FIFO (named pipe)?
	S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
	S_ISSOCK(m) socket?	(Not in POSIX.1-1996.)

	
	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
	*/
	switch (buf->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;
	}
	TESET_ACCESS(buf->st_mode, S_IRUSR);
	TESET_ACCESS(buf->st_mode, S_IWUSR);
	TESET_ACCESS(buf->st_mode, S_IXUSR);
	
	TESET_ACCESS(buf->st_mode, S_IRGRP);
	TESET_ACCESS(buf->st_mode, S_IWGRP);
	TESET_ACCESS(buf->st_mode, S_IXGRP);

	TESET_ACCESS(buf->st_mode, S_IROTH);
	TESET_ACCESS(buf->st_mode, S_IWOTH);
	TESET_ACCESS(buf->st_mode, S_IXOTH);
	
	printf("uid: %d, gid: %d\n", buf->st_uid, buf->st_gid);
	printf("size: %ld\n", buf->st_size);
	printf("links: %ld\n", buf->st_nlink);
}

int main()
{
	int fd = open("t.txt", O_RDWR|O_CREAT|O_APPEND|O_SYNC/*|O_EXCL*/, (S_IRUSR|S_IWUSR)|(S_IRGRP|S_IWGRP)|(S_IROTH));
	if (fd < 0) {
		perror("open error");
	}	

	struct stat buf = {0};
	if (stat("t.txt", &buf) < 0) {
		perror("stat error");
	}
	printf_stat("stat", &buf);

	
	memset(&buf, 0, sizeof(buf));
	if (fstat(fd, &buf) < 0) {
		perror("fstat error");
	}
	printf_stat("fstat", &buf);

	int fddir = open("..", O_RDONLY|O_DIRECTORY); // Need to create capter4 directory
	if (fddir > 0) {
		memset(&buf, 0, sizeof(buf));
		// if (fstatat(fd, "capter4/t.txt", &buf, AT_SYMLINK_NOFOLLOW) < 0) {
		if (fstatat(fddir, "capter4/t.txt", &buf, AT_SYMLINK_NOFOLLOW) < 0) {
			perror("fstatat error");
		}
		printf_stat("fstatat", &buf);	
	}
	//if (access("t.txt", R_OK|W_OK|X_OK) < 0) {
	if (access("t.txt", R_OK|W_OK) < 0) {
		printf("Access test fail.\n");
	}

	mode_t mode = umask(S_IXUSR|S_IXGRP|S_IXOTH);
	printf("mode = %04x\n", mode);
	int fd2 = open("t2.txt", O_RDWR|O_CREAT|O_APPEND, (S_IRWXU)|(S_IRWXG)|(S_IRWXO)); // t2.txt: 0666

	close(fd2);
	if (link("../capter4", "t2.txt.link") < 0) {
	//if (link("t2.txt", "t2.txt.link") < 0) {
		perror("link error");
	}


	return 0;
}

4. 小结

1. 理解文件访问权限和访问模式,了解文件和目录的所有属性

2. 理解用户ID和组ID,包括实际、有效和设置用户ID和组ID

3. 理解文件系统的结构,硬链接和符号链接的区别

3. 掌握文件和目录的创建和删除相关函数,包括相似函数的参数用法及区别(比如函数xx,相似函数fxx、fdxx、xxat、fxxat)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值