Linux 文件相关编程

1. access系统调用
access系统调用用于检测所指定的文件访问权限,原型如下:
#include <unistd.h>

int access(const char *pathname, int mode);
代码示例如下:
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
        if (access(argv[1], F_OK))
                printf("No such file or directory!\n");
        else
                printf("%s\n", argv[1]);

        return 0;
}

其中F_OK用于测试这个文件或目录是否存在,其它mode常量还有R_OK、W_OK、X_OK,分别对应读权限,写权限和可执行权限。access系统调用检测成功的话返回0,否则返回-1,而这些mode常量可以通过或运算形成位掩码,只要其中一项检测没有成功返回值都为-1。


2. link、unlink系统调用
link、unlink系统调用用于创建和删除硬链接,原型如下:

#include <unistd.h>

int link(const char *oldpath, const char *newpath);
int unlink(const char *pathname);
link系统调用中的oldpath是一个已经存在的文件名,而newpath将是要创建硬链接的文件名,如果newpath存在,则不会将其覆盖。

3. rename系统调用
reanme系统有点类似于mv命令,用于重命名一个文件或移动一个文件,原型如下:

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

4. mkdir、rmdir系统调用
mkdir、rmdir系统调用同命令mkdir、rmdir类似,用于创建、删除一个目录,原型如下:
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int mkdir(const char *pathname, mode_t mode);
int rmdir(const char *pathname);

5. remove函数
remove函数用于删除一个文件或目录,同rm命令类似,原型如下:
#include <stdio.h>

int remove(const char *pathname);

6. opendir、readdir、closedir函数
opendir函数用于打开一个目录,原型如下:
#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name);
opendir返回值是一个DIR类型的指针,即所谓的"directory stream",供后续函数使用。

而readdir函数用于读取一个目录,原型如下:
#include <dirent.h>

struct dirent *readdir(DIR *dirp);
其中的dirp指针即是opendir的返回值,每调用一次readdir函数,dirp指针将指向下一个待读取的"directory entry",如果已经读取到"directory stream"的末尾或者出错,将返回一个NULL指针。

再来看看readdir返回值struct dirent,结构体定义如下:
struct dirent {
    ino_t          d_ino;       /* inode number */
    off_t          d_off;       /* offset to the next dirent */
    unsigned short d_reclen;    /* length of this record */
    unsigned char  d_type;      /* type of file; not supported
                                   by all file system types */
    char           d_name[256]; /* filename */
};

closedir函数用于关闭"directory stream",原型如下:
#include <sys/types.h>
#include <dirent.h>

int closedir(DIR *dirp);

好吧,来看一个实例,将一个目录中的所有文件列举出来:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>

int main(int argc, char *argv[])
{
        DIR *dir;
        struct dirent *dp;

        dir = opendir(argv[1]);
        if (dir == NULL) {
                perror("opendir error");
                return -1;
        }

        for (;;) {
                dp = readdir(dir);
                if (dp == NULL)
                        break;

                if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
                        continue; /* skip . and .. */

                printf("%s\n", dp->d_name);
        }

        closedir(dir);

        return 0;
}


//2015.08.13 补
1. stat相关系统调用
stat()、lstat()、fstat()系统调用用于获取文件相关信息,原型如下:

#include <sys/stat.h>

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

其中stat根据文件名来获取文件相关信息。
lstat与stat类似,区别在于如果文件属于符号链接,那么所获取的信息是符号链接本身,而不是符号链接所指向的文件。
fstat则是根据一个打开文件的文件描述符来获取文件相关信息。
而上述系统调用都会将所获取的文件信息存储在struct stat指针所指向的缓冲区中,struct stat类型定义如下:

struct stat {
    dev_t     st_dev;     /* ID of device containing file */
    ino_t     st_ino;     /* inode number */
    mode_t    st_mode;    /* protection */
    nlink_t   st_nlink;   /* number of hard links */
    uid_t     st_uid;     /* user ID of owner */
    gid_t     st_gid;     /* group ID of owner */
    dev_t     st_rdev;    /* device ID (if special file) */
    off_t     st_size;    /* total size, in bytes */
    blksize_t st_blksize; /* blocksize for file system I/O */
    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
    time_t    st_atime;   /* time of last access */
    time_t    st_mtime;   /* time of last modification */
    time_t    st_ctime;   /* time of last status change */
};
这里只针对部分成员加以描述。
st_mode:文件的类型与权限,st_mode总共16位,其中高4位为文件的类型,可以通过宏S_ISREG()、S_ISDIR()等相关宏来判断是普通文件、目录文件等。而低12位则是文件权限位,这里只要知道低9位就是我们常见的例如777就可以了。
st_uid:文件所属用户的id。
st_gid:文件所属组的id。
st_size:文件大小。
st_atime:对应文件的最后访问时间。
st_mtime:对应文件的最后修改时间。
st_ctime:对应文件的状态发生改变时间。

好了,了解了这些,来看一个实例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>

int main(int argc, char *argv[])
{
        struct stat sb;

        if (stat(argv[1], &sb) < 0) {
                perror("stat");
                exit(EXIT_FAILURE);
        }

        printf( "mode \t\t%o\n"
                "uid \t\t%d\n"
                "gid \t\t%d\n"
                "size \t\t%d\n"
                "blocksize \t%d\n"
                "blocks \t\t%d\n" , sb.st_mode, sb.st_uid, sb.st_gid,
                        (int)sb.st_size, (int)sb.st_blksize, (int)sb.st_blocks);

        printf( "atime \t\t%s", ctime(&sb.st_atime));
        printf( "mtime \t\t%s", ctime(&sb.st_mtime));
        printf( "ctime \t\t%s", ctime(&sb.st_ctime));

        exit(EXIT_SUCCESS);
}

2. 改变文件属主
可以通过chown、fchown系统调用来改变文件属主,原型如下:
#include <unistd.h>

int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);

3. 改变文件权限
改变文件权限可以通过chmod、fchmod系统调用,原型如下:
#include <sys/stat.h>

int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);

4. 关于umask
先来看一段代码:
#include <stdio.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
        if (mkdir(argv[1],
                (S_IRWXU | S_IRWXG | S_IRWXO) /*0777*/) < 0) {
                perror("mkdir");
        }

        return 0;
}
这段代码是新建一个目录,目录的权限是0777,但是呢,代码执行之后,结果并不是所预期的那样,创建的目录权限为0775,这是什么原因呢,那就是同这里的umask有关。

umask用于open、mkdir这类系统调用创建文件或目录的权限掩码,用于屏蔽一些权限位,权限计算公式如下:
(mode & ~umask & 0777)
通常umask默认值为0022,其含义是对于同组或其他用户,应屏蔽写权限。假设调用mkdir创建一个目录,其mode为0777,那么创建的目录权限实际为0755。

可以通过umask()系统调用来改变这个掩码值,原型如下:
#include <sys/stat.h>

mode_t umask(mode_t mask);
对于上面代码只需要作出如下修改,创建的目录权限就是我们想要的0777,代码如下:
#include <stdio.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
        umask(0);

        if (mkdir(argv[1],
                (S_IRWXU | S_IRWXG | S_IRWXO) /*0777*/) < 0) {
                perror("mkdir");
        }

        return 0;
}
那么我想获取系统默认的掩码值,怎么获取呢?可以通过下面的方式:
mode_t getumask(void)
{
    mode_t mask = umask( 0 );
    umask(mask);
    return mask;
}
使用umask系统调用会返回之前的掩码值,那么调用getumask一下,当前我的系统掩码值为0002,所以最终创建的目录权限为0775,这就能理解为什么指定0777权限而得到0775权限的原因了。

参考教程:The Linux Programming Interface - A Linux and UNIX System Programming Handbook.pdf

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值