取得拓展属性
#include <sys/types.h>
#include <attr/xattr.h>
ssize_t getxattr(const char* path, const char* key, void* value, size_t size);
ssize_t lgetxattr(const char* path, const char* key, void* value, size_t size);
ssize_t fgetxattr(int fd, const char* key, void* value, size_t size);
执行成功时,getxattr()会从文件path将拓展属性key的值存入value缓冲区,缓冲区的长度为size个字节,并且返回此值的真实大小。
如果size为0,则不会存入value中,只返回值的大小,让应用程序决定缓冲区的大小,方便进行存储。
lgetxattr()的行为如同getxattr(),但是当path是一个符合链接时,返回链接本身的(而非连接的目标文件)的拓展属性。
设定一个拓展属性
#include <sys/types.h>
#include <attr/xattr.h>
int setxattr(const char* path, const char* key, const void* value, size_t size, int flags);
int lsetxattr(const char* path, cosnt char* key, const void* value, size_t size, int flags);
int fsetxattr(int fd, const char* key, const void* value, size_t size, int flags);
列出文件上的拓展属性
#include <sys/types.h>
#include <attr/xattr.h>
ssize_t listxattr(const char* path, char* list, size_t size);
ssize_t llistxattr(const char* path, char* list, size_t size);
ssize_t flistxattr(int fd, char*list, size_t size);
执行成功时,listxattr()返回path文件的拓展属性列表,存入list中,函数返回列表的实际大小,以字节为单位。
每个拓展属性被传入到list并且以NULL字符结尾,如下所示:
“user.md5_sum\0user.mime_type\0system.posix_acl_default\0”
如果调用时size设置为0,函数返回列表的实际长度。
llistxattr()的行为如同listxattr(),当path是一个符号连接时,返回的是链接本身(而不是链接的目标文件)有关的拓展属性。
移除一个拓展属性
#include <sys/types.h>
#include <attr/xattr.h>
int removexattr(const char* path, const char* key);
int lremovexattr(const char* path, const char* key);
int fremovexattr(int fd, const char* key);
获取当前目录
#include <unistd.h>
#include <stdio.h>
int main() {
char *cwd;
cwd = getcwd(NULL, 0);
if(cwd) {
printf("%s", cwd);
}
return 0;
}
LInux的C链接库还提供了一个get_current_dir_name()函数,当buf为NULL而且size=0时,函数如同getcwd()函数
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char *cwd;
cwd = get_current_dir_name();
if(cwd) {
printf("%s", cwd);
}
free(cwd);
return 0;
}
变更当前工作目录
#include <unistd.h>
int chdir(const char* path);
int fchdir(int fd);
chdir()可用于将当前工作目录变更为path所指定的路径名称,可以绝对路径也可以相对路径,fchdir()用于将当前工作目录变更为fd(必须对应到已经打开的目录)所代表的路径名称。
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int swd_fd;
swd_fd = open(".", O_RDONLY);
if (swd_fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 变更为不同的目录
ret = chdir(some_other_dir);
if (ret) {
perror("chdir");
exit(EXIT_FAILURE);
}
// 在新目录中进行其他操作
// 返回所保存的目录中
ret = fchdir(swd_fd);
if (ret) {
perror("fchdir");
exit(EXIT_FAILURE);
}
// 关闭所在目录
ret = close(swd_fd);
if (ret) {
perror("close");
exit(EXIT_FAILURE);
}
return 0;
}
创建目录
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char* path, mode_t mode);
执行成功时,会创建权限为mode(经过umask修改)的目录path。
移除目录
#include <unistd.h>
int rmdir(const char* path);
path路径必须是空的,只能包含‘.’和'..‘路径,没有实现rm -r 的递归删除功能,须手动深度搜索,从叶节点开始删除。
读取一个目录内容
#include <sys/types.h>
#include <dirent.h>
DIR* opendir(const char* name);
执行成功时,会创建一个目录流,表示name所指定的目录。目录流就是一个信息比较多的文件描述符,代表已经打开的目录,因此可以获取特定目录流后面的文件描述符:
#define _BSD_SOURCE
#include <sys/types.h>
#include <dirent.h>
int dirfd(DIR* dir);
执行成功时,返回dir目录流的文件描述符。
从目录流中读取数据
#include <sys/types.h>
#include <dirent.h>
struct dirent* readdir(DIR* dir);
关闭目录流
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR* dir);
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
/**
* find_file_int_dir 从目录path中搜索file的文件
* 存在返回0,否则返回非0
*/
int find_file_in_dir(const char* path, const char* file) {
struct dirent* entry;
int ret = 1;
DIR* dir;
dir = opendir(path);
errno = 0; //这句很重要
while((entry = readdir(dir)) != NULL) {
if (!strcmp(entry->d_name, file)) {
ret = 0;
break;
}
}
if (errno && !entry) {
perror("readdir");
}
closedir(dir);
return ret;
}
int main() {
printf("%d\n", find_file_in_dir(".", "test.c"));
printf("%d\n", find_file_in_dir(".", "aaaa"));
return 0;
}
硬链接
#include <unistd.h>
int link(const char* oldpath, const char* newpath);
调用成功之后,oldpath和newpath会指向同一个文件,无法区分谁是最初的链接。
符号链接
#include <unistd.h>
int symlink(const char* oldpath, const char* newpath);
解除链接
#include <unistd.h>
int unlink(const char* pathname);
#include <stdio.h>
int remove(const char* path);
执行成功时,remove会从文件系统中删除path并且返回0,如果path是一个文件,调用unlink,如果path是一个目录,则调用rmdir()
移动
#include <stdio.h>
int rename(const char* oldpath, const char* newpath);
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
#include <sys/stat.h>
int main(int argc, char** argv) {
int fd, ret;
if (argc < 2) {
fprintf(stderr, "usage: %s < device to eject>\n", argv[0]);
return 1;
}
/**
* 以只读方式打开CD-ROM设备,O_NONBLOCK用于通知内核,即使
* 设备中没有媒体,也要打开设备
*/
fd = open(argv[1], O_RDONLY | O_NONBLOCK);
if (fd < 0) {
perror("open");
return 1;
}
/**
* 给CD-ROM设备送出弹出命令
*/
ret = ioctl(fd, CDROMEJECT, 0);
if (ret) {
perror("ioctl");
return 1;
}
ret = close(fd);
if (ret) {
perror("close");
return 1;
}
return 0;
}
初始化inotify
#include <inotify.h>
int inotify_init(void);
加入一个新的监视项目
#include <inotify.h>
int inotify_add_watch(int fd, const char* path, uint32_t mask);
为path文件或者目录添加一个mask所描述的监听项目至fd所表示的inotify实例。
int wd;
wd = inotify_add_watch(fd, "/etc", IN_ACCESS | IN_MODIFY);
if (wd == -1) {
perror("inotify_add_watch");
exit(EXIT_FAILLURE);
}
此范例会在/etc所在目录上的所有读取和写入加上一个监视项目,如果/etc中任何文件被读取或者写入,inotify会传送一个事件给inotify文件描述符fd,提供给监视描述符wd。
inotify事件
读取inotify事件
char buf[BUF_LEN]__attribute__((aligned(4)));
ssize_t len, i = 0;
// 读取BUF_LEN个字节的事件
len = read(fd, buf, BUF_LEN);
// 读取每个事件直到读完为止
while(i < len) {
struct inotify_event * event = (struct inotify_event*) &buf[i];
printf("wd=%d mask=%d cookie=%d len=%d dir=%s\n", event->wd,
event->mask, event->cookie,event->len, (event->mask & IN_ISDIR)?"yes":"no");
//如果有一个名称,则输出它
if(event->len)
printf("name=%d\n", event->name);
//将索引更新为下一个事件的开头
i += sizeof(struct inotify_event) + event->len;
}
因为inotify文件描述符的行为如同一个常规文件,可以使用select,poll,epoll监听。
int wd;
/**
* 只有在/etc/init.d 是一个目录,且他的路径中没有一个部分是符号链接时,
* 才会监视/etc/init.d是否被移动过
*/
wd = inotify_add_watch(fd, "/etc/init.d", IN_MOVE_SELF | IN_ONLYDIR | IN_DONT_FOLLOW);
if (wd == -1) {
perror("inotify_add_watch");
}
移除一个inotify监视项目
#include <inotify.h>
int inotify_rm_watch(int fd, uint32_t wd);
取得事件队列的大小
#include <sys/ioctl.h>
unsigned int queue_len;
int ret;
ret = ioctl(fd, FIONREAD, &queue_len);
if (ret < 0)
perror("ioctl");
else
printf("%u bytes pending in queue\n", queue_len);
销毁一个inotify实例
int ret;
// fd 经 inotify_init() 取得
ret = close(fd);
if (fd == -1)