TLPI读书笔记第18章-目录与链接3

1.列出目录中的所有文件

/* Listing 18-2 */

/* list_files.c*/
#if defined(__APPLE__)
/* Darwin requires this header before including <dirent.h> */
#include <sys/types.h>
#endif

#include <dirent.h>
#include "tlpi_hdr.h"

static void             /* 列出目录'dirpath'的所有文件 */
listFiles(const char *dirpath) {
    DIR *dirp;
    struct dirent *dp;
    Boolean isCurrent;          /* 判断dirpath是否是当前目录. */

    isCurrent = strcmp(dirpath, ".") == 0;
/**打开指定目录,返回一个DIR指针*/
    dirp = opendir(dirpath);
    if (dirp == NULL) {
        errMsg("opendir failed on '%s'", dirpath);
        return;
    }

    /* 读取每个DIR条目,打印目录+文件名 */

    for (;;) {
        errno = 0;              /* 打印readdir过程中错误 */
        dp = readdir(dirp);
        if (dp == NULL)
            break;
     /**如果d_name是.或..,继续循环*/
        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
            continue;
     /**如果是当前目录,则不打印dir部分*/
        if (!isCurrent)
            printf("%s/", dirpath);
        printf("%s
", dp->d_name);
    }

    if (errno != 0)
        errExit("readdir");

    if (closedir(dirp) == -1)
        errMsg("closedir");
}

int
main(int argc, char *argv[]) {
    if (argc > 1 && strcmp(argv[1], "--help") == 0)
        usageErr("%s [dir-path...]
", argv[0]);

    if (argc == 1)              /* 没有传参数,则默认是当前目录. */
        listFiles(".");
    else
        for (argv++; *argv; argv++)
            listFiles(*argv);

    exit(EXIT_SUCCESS);
}

2.递归遍历目录

/* Listing 18-3 */

/* nftw_dir_tree.c

*/
#if defined(__sun)
#define _XOPEN_SOURCE 500       /* Solaris 8 needs it this way */
#else
#if ! defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
#define _XOPEN_SOURCE 600       /* Get nftw() and S_IFSOCK declarations */
#endif
#endif
#include <ftw.h>
#include "tlpi_hdr.h"

static void
usageError(const char *progName, const char *msg)
{
    if (msg != NULL)
        fprintf(stderr, "%s
", msg);
    fprintf(stderr, "Usage: %s [-d] [-m] [-p] [directory-path]
", progName);
    fprintf(stderr, "	-d Use FTW_DEPTH flag
");
    fprintf(stderr, "	-m Use FTW_MOUNT flag
");
    fprintf(stderr, "	-p Use FTW_PHYS flag
");
    exit(EXIT_FAILURE);
}

static int                      /* 自定义函数,以备nftw()调用 */
dirTree(const char *pathname, const struct stat *sbuf, int type,struct FTW *ftwb)
{
    if (type == FTW_NS) {                  /* 调用stat失败 */
        printf("?");
    } else {
        switch (sbuf->st_mode & S_IFMT) {  /* 打印文件类型 */
        case S_IFREG:  printf("-"); break;
        case S_IFDIR:  printf("d"); break;
        case S_IFCHR:  printf("c"); break;
        case S_IFBLK:  printf("b"); break;
        case S_IFLNK:  printf("l"); break;
        case S_IFIFO:  printf("p"); break;
        case S_IFSOCK: printf("s"); break;
        default:       printf("?"); break; /* Should never happen (on Linux) */
        }
    }

    printf(" %s  ", (type == FTW_D)  ? "D  " : (type == FTW_DNR) ? "DNR" :
            (type == FTW_DP) ? "DP " : (type == FTW_F)   ? "F  " :
            (type == FTW_SL) ? "SL " : (type == FTW_SLN) ? "SLN" :
            (type == FTW_NS) ? "NS " : "  ");

    if (type != FTW_NS)
        printf("%7ld ", (long) sbuf->st_ino);
    else
        printf("        ");

    printf(" %*s", 4 * ftwb->level, "");        /* 用缩进代表级别 */
    printf("%s
",  &pathname[ftwb->base]);     /* 打印basename */
    return 0;                                   /* Tell nftw() to continue */
}

int main(int argc, char *argv[])
{
    int flags, opt;

    flags = 0;
    while ((opt = getopt(argc, argv, "dmp")) != -1) {
        switch (opt) {
        case 'd': flags |= FTW_DEPTH;   break;/*后序遍历*/
        case 'm': flags |= FTW_MOUNT;   break;/*不越界进入另一个文件系统*/
        case 'p': flags |= FTW_PHYS;    break;/*不对符号链接解引用*/
        default:  usageError(argv[0], NULL);
        }
    }

    if (argc > optind + 1)
        usageError(argv[0], NULL);

    if (nftw((argc > optind) ? argv[optind] : ".", dirTree, 10, flags) == -1) {
        perror("nftw");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

3.打印路径中的目录和文件名

/* Listing 18-5 */

/* t_dirbasename.c

*/
#include <libgen.h>
#include "tlpi_hdr.h"
/**打印路径的目录部分和文件名部分
 * dirname()和 basename()均可修改pathname所指向的字符串。
 * 因此,如果希望保留原有的路径名字符串,那么就必须向 dirname()和 basename()传递该字符串的副本
 * 使用strdup()该函数调用了 malloc()来制作传递给dirname()和basename()的字符串副本,
 * 然后再使用 free()将其释放
 * */
int
main(int argc, char *argv[])
{
    char *t1, *t2;
    int j;

    for (j = 1; j < argc; j++)  {
        t1 = strdup(argv[j]);
        if (t1 == NULL)
            errExit("strdup");
        t2 = strdup(argv[j]);
        if (t2 == NULL)
            errExit("strdup");

        printf("%s ==> %s + %s
", argv[j], dirname(t1), basename(t2));

        free(t1);
        free(t2);
    }

    exit(EXIT_SUCCESS);
}

4.unlink的应用

/* Listing 18-1 */

/** t_unlink.c
    一个文件被unlink,当他还有被打开的文件描述符时他实际是没有被删的,
    此时还能进行写入,close(fd)后文件才真正被删
    Usage: t_unlink file
*/
#include <sys/stat.h>
#include <fcntl.h>
#include "tlpi_hdr.h"

#define CMD_SIZE 200
#define BUF_SIZE 1024

int
main(int argc, char *argv[])
{
    int fd, j, numBlocks;
    char shellCmd[CMD_SIZE];            /* 调用的shell命令 */
    char buf[BUF_SIZE];                 /* 随机写入一定字节 */

    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s temp-file [num-1kB-blocks] 
", argv[0]);

    numBlocks = (argc > 2) ? getInt(argv[2], GN_GT_0, "num-1kB-blocks")
                           : 100000;

    /* 创建一个新文件 */

    fd = open(argv[1], O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
        errExit("open");

    if (unlink(argv[1]) == -1)          /* 删除文件 */
        errExit("unlink");

    for (j = 0; j < numBlocks; j++)     /* 写入文件 */
        if (write(fd, buf, BUF_SIZE) != BUF_SIZE)
            fatal("partial/failed write");
    /**将命令df写入shellCmd中,并执行shell命令*/
    snprintf(shellCmd, CMD_SIZE, "df -k `dirname %s`", argv[1]);
    system(shellCmd);                   /* 查看文件占用空间 */

    if (close(fd) == -1)                /* 关闭文件描述符,此时文件才被删除 */
        errExit("close");
    printf("********** Closed file descriptor
");

    system(shellCmd);                   /* 重新查看占用空间 */
    exit(EXIT_SUCCESS);
}

5.读取并解析一个符号链接

/* Listing 18-4 */

/* view_symlink.c

   读取并解析一个符号链接
*/
#include <sys/stat.h>
#include <limits.h>             /* For definition of PATH_MAX */
#include "tlpi_hdr.h"

#define BUF_SIZE PATH_MAX

int
main(int argc, char *argv[])
{
    struct stat statbuf;
    char buf[BUF_SIZE];
    ssize_t numBytes;

    if (argc != 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s pathname
", argv[0]);

    /* 检查提供的路径名是否为一个符号链接 */

    if (lstat(argv[1], &statbuf) == -1)
        errExit("lstat");

    if (!S_ISLNK(statbuf.st_mode))
        fatal("%s is not a symbolic link", argv[1]);

    numBytes = readlink(argv[1], buf, BUF_SIZE - 1);
    if (numBytes == -1)
        errExit("readlink");
    buf[numBytes] = '';                       /* 添加终止空字节,并打印 */
    printf("readlink: %s --> %s
", argv[1], buf);

    if (realpath(argv[1], buf) == NULL)
        errExit("realpath");
    printf("realpath: %s --> %s
", argv[1], buf);

    exit(EXIT_SUCCESS);
}
原文地址:https://www.cnblogs.com/wangbin2188/p/14663985.html