scandir函数的研究【笔记】

简介: 以下是本人的学习笔记,代码并非原创,均摘自官方源码,贴出来仅供学习记录用 scandir 的使用要注意内存泄漏的问题 scandir函数实现: vi ./uClibc-0.9.33.2/libc/misc/dirent/scandir.

以下是本人的学习笔记,代码并非原创,均摘自官方源码,贴出来仅供学习记录用

scandir 的使用要注意内存泄漏的问题

scandir函数实现:

vi ./uClibc-0.9.33.2/libc/misc/dirent/scandir.c

/*
 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
 *
 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 */

#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include "dirstream.h"

int scandir(const char *dir, struct dirent ***namelist,
    int (*selector) (const struct dirent *),
    int (*compar) (const struct dirent **, const struct dirent **))
{
    DIR *dp = opendir (dir);
    struct dirent *current;
    struct dirent **names = NULL;
    size_t names_size = 0, pos;
    int save;

    if (dp == NULL)
    return -1;

    save = errno;
    __set_errno (0);

    pos = 0;
    while ((current = readdir (dp)) != NULL) {
    int use_it = selector == NULL;

    if (! use_it)
    {
        use_it = (*selector) (current);
        /* The selector function might have changed errno.
         * It was zero before and it need to be again to make
         * the latter tests work.  */
        if (! use_it)
        __set_errno (0);
    }
    if (use_it)
    {
        struct dirent *vnew;
        size_t dsize;

        /* Ignore errors from selector or readdir */
        __set_errno (0);

        if (unlikely(pos == names_size))
        {
        struct dirent **new;
        if (names_size == 0)
            names_size = 10;
        else
            names_size *= 2;
        new = (struct dirent **) realloc (names,
                    names_size * sizeof (struct dirent *));
        if (new == NULL)
            break;
        names = new;
        }

        dsize = &current->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current;
        vnew = (struct dirent *) malloc (dsize);
        if (vnew == NULL)
        break;

        names[pos++] = (struct dirent *) memcpy (vnew, current, dsize);
    }
    }

    if (unlikely(errno != 0))
    {
    save = errno;
    closedir (dp);
    while (pos > 0)
        free (names[--pos]);
    free (names);
    __set_errno (save);
    return -1;
    }

    closedir (dp);
    __set_errno (save);

    /* Sort the list if we have a comparison function to sort with.  */
    if (compar != NULL)
    qsort (names, pos, sizeof (struct dirent *), (comparison_fn_t) compar);
    *namelist = names;
    return pos;
}

例子参考1:

vi ./uClibc-0.9.33.2/test/stdlib/qsort.c

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>

static int select_files(const struct dirent *dirbuf)
{
    if (dirbuf->d_name[0] == '.')
        return 0;
    else
        return 1;
}

int main(void)
{
    struct dirent **array;
    struct dirent *dirbuf;

    int i, numdir;

    chdir("/");
    numdir = scandir(".", &array, select_files, NULL);
    printf("\nGot %d entries from scandir().\n", numdir);
    for (i = 0; i < numdir; ++i) {
        dirbuf = array[i];
        printf("[%d] %s\n", i, dirbuf->d_name);
        free(array[i]);
    }
    free(array);
    numdir = scandir(".", &array, select_files, alphasort);
    printf("\nGot %d entries from scandir() using alphasort().\n", numdir);
    for (i = 0; i < numdir; ++i) {
        dirbuf = array[i];
        printf("[%d] %s\n", i, dirbuf->d_name);
    }
    printf("\nCalling qsort()\n");
    /* Even though some manpages say that alphasort should be
     * int alphasort(const void *a, const void *b),
     * in reality glibc and uclibc have const struct dirent**
     * instead of const void*.
     * Therefore we get a warning here unless we use a cast,
     * which makes people think that alphasort prototype
     * needs to be fixed in uclibc headers.
     */
    qsort(array, numdir, sizeof(struct dirent *), (void*) alphasort);
    for (i = 0; i < numdir; ++i) {
        dirbuf = array[i];
        printf("[%d] %s\n", i, dirbuf->d_name);
        free(array[i]);
    }
    free(array);
    return (0);
}

例子参考2:

man scandir

EXAMPLE
       #define _SVID_SOURCE
       /* print files in current directory in reverse order */
       #include <dirent.h>

       int
       main(void)
       {
           struct dirent **namelist;
           int n;

           n = scandir(".", &namelist, NULL, alphasort);
           if (n < 0)
               perror("scandir");
           else {
               while (n--) {
                   printf("%s\n", namelist[n]->d_name);
                   free(namelist[n]);
               }
               free(namelist);
           }
       }

 

【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
|
存储 算法 Linux
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
457 0
|
存储 算法 C++
【C++ 包装器类 map】C++ 标准库(std)中的map结构 哈希表(unordered_map)和黑红树(map)教程
【C++ 包装器类 map】C++ 标准库(std)中的map结构 哈希表(unordered_map)和黑红树(map)教程
1171 1
|
Linux 网络安全 Windows
CentOs主机能够ping通虚拟机,虚拟机无法ping通主机 解决方案
CentOs主机能够ping通虚拟机,虚拟机无法ping通主机 解决方案
776 0
CentOs主机能够ping通虚拟机,虚拟机无法ping通主机 解决方案
|
SQL
SQL基础——集合运算(下)
SQL基础——集合运算(下)
172 0
|
关系型数据库 MySQL Linux
Linux_Centos7在安装Mysql常见错误
Linux_Centos7在安装Mysql常见错误依赖时失败 问题一:Centos7在安装Mysql依赖(libs)或客户端(client)时失败 问题二:Centos7在安装Mysql服务器(server)时失败
1710 1
|
人工智能 IDE API
灵动指尖 :阿里云智能编码插件 更好的为IDE内置社区服务
灵动指尖 :阿里云智能编码插件 更好的为IDE内置社区服务
1524 0
QT 重写控件(QPushButton为例)实现背景图片的切换和鼠标样式切换
一般在QT开发中,使用setCursor()给控件设置鼠标的样式效果(一般是手型和箭头的切换),一般情况下,这个函数也是起作用的,但是一旦调用了全局QApplication::setOverrideCursor()设置鼠标效果后,在使用setCursor给控件设置鼠标样式就不起效果了,这是QT的机制
638 0
|
传感器 缓存 Shell
mqtt服务器搭建及homeassistant使用
本文介绍了服务器的基础配置,并利用服务器安装docker,搭建mqtt服务器传输数据,并利用homeassistant显示数据。
mqtt服务器搭建及homeassistant使用
|
SQL 存储 分布式计算
SpringBoot集成Jpa极简教程
基本概念 Jpa(Java Persistence API)即 java 持久化api规范,并不是一个ORM框架,而是一种访问数据的接口定义,通过与数据访问框架或者ORM框架配合,可以简单方便的处理与数据库的交互。这种概念有点类似 slf4j 和 logback 的关系。 SpringDataJpa是对JPA规范的封装,旨在提高开发效率,同时不失灵活性,它提供了一种简单、一致的方式来访问不同种类的数据源,包括关系数据库、非关系数据库、MapReduce 框架等。Spring Data JPA 还提供了一些高级特性,如动态查询、多表查询、嵌套查询、存储过程和函数调用等。
597 0
SpringBoot集成Jpa极简教程