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);
}