sliver__

[Directory Management] - scandir 함수 본문

CS/UNIX

[Directory Management] - scandir 함수

sliver__ 2022. 10. 22. 18:02
728x90
  • 프로토타입은 아래와 같다.
#include <sys/types.h>
#include <dirent.h>

int scandir(
    const char *dirname,
    struct dirent ***namelist,
    int (*select)(struct dirent *),
    int (*compar)(const void *, const void *));

int alphasort(const void *d1, const void *d2);
  • dirname 인수에는 스캔하려는 디렉토리의 경로 이름이 제공된다. 
  • namelist 인수는 (struct dirent **) 포인터를 가리키므로 디렉터리 항목 목록이 반환될 수 있다. 
  • 모든 디렉토리 이름을 선택하려는 경우 인수 select를 null로 둘 수 있다. 
  • 인수 compar에 널 포인터가 주어지면 반환된 디렉토리 항목은 정렬되지 않는다.
  • 성공적으로 반환되면 scandir은 namelist 배열에 반환된 항목 수를 반환합다(여기에는 값 0이 포함될 수 있음). 
  • 오류가 있는 경우 값 -1이 반환된다(errno 값이 공식적으로 문서화되지 않은 것으로 나타남).
  • alphasort(3) 함수는 이름 목록을 알파벳순으로 정렬해야 하는 경우 인수 비교에서 제공할 수 있는 함수이다.
  • namelist 배열은 동적으로 할당되며 프로그램에서 더 이상 필요하지 않을 때 해제해야 한다. 
  • 먼저 배열의 각 항목에 대해 free을 호출한 다음 free를 호출하여 배열 자체를 해제해야 합니다

 

[scandir 선택 함수 선언]

  • select 인수에 제공된 함수 포인터는 dirent 구조에 대한 하나의 포인터로 호출된다. 
  • 이를 기반으로 항목이 최종 항목 목록에 포함되려면 0이 아닌 값(true)을 반환해야 한다. 
  • 이 함수가 0(거짓)을 반환하면 항목이 제외된다.
  • 다음은 h로 시작하는 항목만 선택하는 예제 함수이다.
/*
 * Select only those directory entries that start with 'h'
 */
int
my_select(struct dirent *dp) {

    if ( dp->d_name[0] != 'h')
        return 0;                       /* Don't include this */
    return 1;                           /* else include this one */
}

 

[scandir 비교 함수 선언]

int
my_compar(const void *d1,const void *d2) {
    struct dirent *dir1 = *(struct dirent **)d1;
    struct dirent *dir2 = *(struct dirent **)d2;

    return strcmp(dir1->d_name,dir2->d_name);
}
  • 표시된 코드는 alphasort 함수가 제공하는 것을 구현한다. 
  • 두 개의 void 포인터는 (struct dirent **)로 캐스팅된 다음 struct dirent 항목 자체를 가리키기 위해 한 번 역참조된다. 
  • 이 작업이 완료되면 strcmp를 호출하여 반환할 비교 결과를 제공한다.

 

[scandir 예제]

1:   #include <stdio.h>
2:   #include <stdlib.h>
3:   #include <unistd.h>
4:   #include <errno.h>
5:   #include <sys/types.h>
6:   #include <dirent.h>
7:  
8:   extern int scandir(const char *dirname, struct dirent ***namelist,
9:       int (*select)(struct dirent *),
10:      int (*compar)(const void *, const void *));
11: 
12:  extern int alphasort(const void *d1, const void *d2);
13: 
14:  /*
15:   * Select only those directory entries that start with
16:   * 'h'to demonstrate the selection ability :
17:   */
18:  static int
19:  my_select(struct dirent *dp) {
20: 
21:      if ( dp->d_name[0] != 'h')
22:          return 0;                       /* Don't include this */
23:      return 1;                           /* else include this one */
24:  }
25: 
26:  /*
27:   * Sort entries in reverse order for demonstration
28:   * purposes :
29:   */
30:  static int
31:  my_compar(const void *d1,const void *d2) {
32:      struct dirent *dir1 = *(struct dirent **)d1;
33:      struct dirent *dir2 = *(struct dirent **)d2;
34: 
35:      /*
36:       * Reverse the comparison by reversing
37:       * dir2 with dir1 in the strcmp(3) call:
38:       */
39:      return strcmp(dir2->d_name,dir1->d_name);
40:  }
41: 
42:  /*
43:   * A good test is the directory /etc :
44:   */
45:  int
46:  main(int argc,char **argv) {
47:      int x;                              /* Work index */
48:      int n;                              /* namelist[n] */
49:      struct dirent **namelist;           /* List of names */
50: 
51:      if ( argc < 2 ) {
52:          fputs("A pathname argument is required.\n"
53:              "Try /etc for the directory.\n",stderr);
54:          return 1;
55:      }
56:     
57:      /*
58:       * Scan the directory given :
59:       */
60:      n = scandir(argv[1],&namelist,my_select,my_compar);
61: 
62:      /*
63:       * Report the directory entries :
64:       */
65:      printf("%d entries for %s:\n",n,argv[1]);
66:      for ( x=0; x<n; ++x )
67:          printf("%3d: %s\n",x,namelist[x]->d_name);
68: 
69:      if ( n > 0 ) {
70:          for ( x=0; x<n; ++x )
71:              free(namelist[x]);          /* Release entry */
72:          free(namelist);                 /* Release the array */
73:      }
74:      return 0;
75:  }
$ make scandir
cc -c -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -Wall scandir.c
cc scandir.o -o scandir
$ ./scandir /etc
5 entries for /etc:
  0: hosts.lpd
  1: hosts.equiv
  2: hosts.allow
  3: hosts
  4: host.conf
$
728x90

'CS > UNIX' 카테고리의 다른 글

[GDB] debug 팁  (0) 2022.10.28
[Directory Management] - telldir / seekdir 함수  (0) 2022.10.22
[Directory Management] - rewinddir 함수  (0) 2022.10.22
[Directory Management] - opendir 함수  (0) 2022.10.22
[Directory Management] - rmdir 함수  (0) 2022.10.22
Comments