zoukankan      html  css  js  c++  java
  • 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("
    Got %d entries from scandir().
    ", numdir);
        for (i = 0; i < numdir; ++i) {
            dirbuf = array[i];
            printf("[%d] %s
    ", i, dirbuf->d_name);
            free(array[i]);
        }
        free(array);
        numdir = scandir(".", &array, select_files, alphasort);
        printf("
    Got %d entries from scandir() using alphasort().
    ", numdir);
        for (i = 0; i < numdir; ++i) {
            dirbuf = array[i];
            printf("[%d] %s
    ", i, dirbuf->d_name);
        }
        printf("
    Calling qsort()
    ");
        /* 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
    ", 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
    ", namelist[n]->d_name);
                       free(namelist[n]);
                   }
                   free(namelist);
               }
           }
  • 相关阅读:
    Linux系统下ZIP文件解压和压缩命令
    解析XML文件
    数组和集合之间的转换
    数据库密码到期修改密码
    Linux系统中启动jar程序
    JSONArray依赖包
    多态性
    接口----interface
    抽象类
    final关键字
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/8183958.html
Copyright © 2011-2022 走看看