LInux系统编程(3)

取得拓展属性

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值