C言語システムコール-getdents

getdentsシステムコール

概要

getdentsはディレクトリエントリを取得します。

getdentsは直接呼び出すことを想定されていません。

通常、Cライブラリのreaddir()を通してgetdentsを呼び出すことが推奨されています。


OSによってはgetdentsシステムコールは直接呼び出すことができません。

syscallで間接的にシステムコールを呼び出すことで使用できます。

ただし、sys/syscall.hでgetdentsの定義が削除されている場合には呼び出せません。


getdentsが呼び出せる場合には以下のように使用します。


while((rcount = getdents(fd, buf, BUFSIZ)) > 0){
    for(dp = buf; (char *)dp < (char *)buf + rcount;
         dp = (struct dirent *)((char *)dp + dp->d_reclen))
    printf("%s\n",dp->d_name);
}

サンプルプログラム


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>

#ifdef __linux__
  #include <linux/types.h>
  #include <linux/dirent.h>
  #include <linux/unistd.h>
#else
  #include <sys/dirent.h>
#endif

/*!
 * @brief     
 * @param[in] filepath  ファイルパス名
 * @return    0:success/-1:failure
 */
static int
sample_func(char *filepath)
{
    int fd = 0;
    char buf[BUFSIZ] = {"¥0"};
    int dsize = 0;
    int cnt = 0;

    fd = open(filepath, O_RDONLY);
    if(fd < 0){
        printf("Error: open() %s: %s\n", strerror(errno), filepath);
        return(-1);
    }

    while(1){
        dsize = syscall(SYS_getdents, fd, (struct dirent *)&buf,
                        sizeof(buf));
        if(dsize < 0){
            printf("Error: getdents() %s\n", strerror(errno));
            close(fd);
            return(-1);
        }
        if(dsize == 0) break;

        for(cnt = 0; cnt < dsize;
            cnt +=((struct dirent *)&buf[cnt])->d_reclen){
            printf("%s\n", ((struct dirent *)&buf[cnt])->d_name);
        }
    }

    close(fd);

    return(0);
}

int
main(int argc, char *argv[])
{
    int rc = 0;

    if(argc != 2){
        fprintf(stderr, "Usage: %s <path>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    rc = sample_func(argv[1]);
    if(rc != 0) exit(EXIT_FAILURE);

    exit(EXIT_SUCCESS);
}



関連ページ