UNIX环境高级编程——文件和目录

一、获取文件/目录的属性信息

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
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 */
};
示例程序:

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

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

#define MAJOR(a) (int)((unsigned short)a >> 8)  // 高8位,主设备号
#define MINOR(a) (int)((unsigned short)a & 0xFF)

int filetype(struct stat *buf)
{
    int flag = 0;
    printf("Filetype:");
    mode_t mode;
    mode = buf->st_mode;
    switch (mode & S_IFMT)
    {

    case S_IFSOCK:
        printf("socket\n");
        break;
    case S_IFLNK:
        printf("symbolic link\n");
        break;
    case S_IFREG:
        printf("regular file\n");
        break;
    case S_IFBLK:
        printf("block device\n");
        flag = 1;
        break;
    case S_IFDIR:
        printf("directory\n");
        break;
    case S_IFCHR:
        printf("character device\n");
        flag = 1;
        break;
    case S_IFIFO:
        printf("FIFO\n");
        break;
    default:
        printf("unknown file type\n");
        break;
    }

    return flag;
}

void fileperm(struct stat *buf, char perm[])
{
    strcpy(perm, "----------");
    perm[0] = '?';
    mode_t mode;
    mode = buf->st_mode;
    switch (mode & S_IFMT)
    {

    case S_IFSOCK:
        perm[0] = 's';
        break;
    case S_IFLNK:
        perm[0] = 'l';
        break;
    case S_IFREG:
        perm[0] = '-';
        break;
    case S_IFBLK:
        perm[0] = 'b';
        break;
    case S_IFDIR:
        perm[0] = 'd';
        break;
    case S_IFCHR:
        perm[0] = 'c';
        break;
    case S_IFIFO:
        perm[0] = 'p';
        break;
    }

    if (mode & S_IRUSR)
        perm[1] = 'r';
    if (mode & S_IWUSR)
        perm[2] = 'w';
    if (mode & S_IXUSR)
        perm[3] = 'x';
    if (mode & S_IRGRP)
        perm[4] = 'r';
    if (mode & S_IWGRP)
        perm[5] = 'w';
    if (mode & S_IXGRP)
        perm[6] = 'x';
    if (mode & S_IROTH)
        perm[7] = 'r';
    if (mode & S_IWOTH)
        perm[8] = 'w';
    if (mode & S_IXOTH)
        perm[9] = 'x';
    perm[10] = '\0';
}


int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage %s file\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    printf("Filename:%s\n", argv[1]);
    struct stat sbuf;
    if (lstat(argv[1], &sbuf) == -1)
        ERR_EXIT("stat error");

    printf("file in Dev number:major %d, minor %d\n",
           MAJOR(sbuf.st_dev), MINOR(sbuf.st_dev));
    printf("File inode:%d\n", (int) sbuf.st_ino);

    if (filetype(&sbuf))
    {
        printf("Device number:major %d, minor %d\n",
               MAJOR(sbuf.st_rdev), MINOR(sbuf.st_rdev));
    }

    char perm[11] = {0};
    fileperm(&sbuf, perm);
    printf("File permission bits=%o %s\n", sbuf.st_mode & 07777, perm);

    return 0;
}
测试如下:

huangcheng@ubuntu:~$ ./a.out hc
Filename:hc
file in Dev number:major 8, minor 1
File inode:929485
Filetype:regular file
File permission bits=644 -rw-r--r--

二、目录的访问

功能说明:打开一个目录
原型:DIR*  opendir(char *pathname);

返回值:
打开成功,返回一个目录指针
打开失败,则返回NULL


功能说明:访问指定目录中下一个连接的细节
原型:struct  dirent*  readdir(DIR  *dirptr);

返回值:
返回一个指向dirent结构的指针,它包含指定目录中下一个连接的细节;
没有更多连接时,返回NULL


功能说明:关闭一个已经打开的目录
原型:int closedir (DIR  *dirptr);

返回值:调用成功返回0,失败返回-1


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 */
 };

三、目录的创建删除和权限设置

功能说明:用来创建一个称为pathname的新目录,它的权限位设置为mode
原型:int  mkdir(char *pathname,mode_t mode);

返回值:调用成功返回0,失败返回-1


功能说明:删除一个空目录
原型:int  rmdir(char *pathname);

返回值:调用成功返回0,失败返回-1


功能说明:用来改变给定路径名pathname的文件的权限位。为了改变一个文件的权限位,进程的有效用户ID必须等于文件的所有者ID,或者该进程必须具有超级用户的权限。
原型:int  chmod (char *pathname, mode_t mode);

int  fchmod (int  fd, mode_t mode);

返回值:调用成功返回0,失败返回-1


功能说明:用来改变文件所有者的识别号(owner id)或者它的用户组识别号(group ID),如若两个参数owner或group中的任意一个为-1,则对应的ID不变。
原型:int  chown (char *pathname, uid_t owner,gid_t group);

int  fchown (int  fd, uid_t owner,gid_t group);

返回值:调用成功返回0,失败返回-1

示例代码:

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

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(int argc, char *argv[])
{
    DIR *dir = opendir(".");
    struct dirent *de;
    while ((de = readdir(dir)) != NULL)
    {
        if (strncmp(de->d_name, ".", 1) == 0)
            continue; //忽略隐藏文件
        printf("%s\n", de->d_name);
    }

    closedir(dir);
    exit(EXIT_SUCCESS); // 等价于return 0
}

四、文件长度
     stat结构成员st_size表示以字节为单位的文件长度。此字段只对普通文件、目录文件盒符号链接有意义。
     对于普通文件,其文件长度可以是0,在读这种文件时,将得到文件结束指示。
     对于目录,文件长度通常是一个数(例如512)的倍数。

     对于符号链接,文件长度是文件名中的实际字节数(即huangcheng的符号链接为10,不包括c语言用作名字结尾的null字符)


五、文件截短

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
    这两个函数将把现有的文件长度截短length字节。如果该文件以前的长度大于length,则超过length以外的数据就被删除。


六、chdir、fchdir和getcwd函数

     每个进程都有一个当前目录,此目录是搜索所有相对路径名的起点。当前工作目录是进程的一个属性,起始目录则是登陆名(/etc/passwd)的一个属性。

int chdir(const char *path);
int fchdir(int fd);

    这两个函数中,分别用path或打开文件描述符指定新的当前工作目录。


char *getcwd(char *buf, size_t size);

    把当前目录的绝对地址保存到 buf 中,buf 的大小为 size。如果 size太小无法保存该地址,返回 NULL 并设置 errno 为 ERANGE。可以采取令 buf 为 NULL并使 size 为负值来使 getcwd 调用 malloc 动态给 buf 分配,但是这种情况要特别注意使用后释放缓冲以防止内存泄漏。

你可能感兴趣的:(UNIX环境高级编程——文件和目录)