linux 应用层可以使用opendir, readdir, closedir接口进行文件夹遍历.
API接口位于 linux/fs/readdir.c
linux driver层, 则可以使用file_operation中的readdir接口进行读取.
typedef int (*filldir_t)(void *, const char *, int, loff_t, u64, unsigned); struct file_operations { int (*readdir) (struct file *, void *, filldir_t); };
示例如下:
以下是查找指定目录下的.txt或.ini文件
static int tmp_filldir(void *buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type) { unsigned long d_ino; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { return -EOVERFLOW; } if (namelen > 0) { memcpy(buf, name, namelen); return 0; } return -ENOENT; } static int linux_get_file_path(const char *dirpath, char *full_path) { struct file *pfile; mm_segment_t old_fs; char read_buf[100] = {0}; int ret; int err; pfile = filp_open(dirpath, O_RDONLY, 0); if (IS_ERR(pfile)) { pr_err("Open %s failed!\n", dirpath); return -EINVAL; } old_fs = get_fs(); set_fs(KERNEL_DS); err = -ENOENT; if (pfile->f_op->readdir) { while (true) { ret = pfile->f_op->readdir(pfile, read_buf, tmp_filldir); if (ret || (read_buf[0] == '\0')) { break; } if (strstr(read_buf, ".txt") || strstr(read_buf, ".TXT") || strstr(read_buf, ".ini") || strstr(read_buf, ".ini")) { // for too long filename *(extstr+4) = '\0'; snprintf(full_path, PATH_MAX, "%s/%s", dirpath, read_buf); pr_err("find file: %s\n", read_buf); err = 0; break; } memset(read_buf, 0, 100); } } filp_close(pfile, NULL); set_fs(old_fs); return err; }
#define MY_DIR "/sdcard/my/dir" char *filepath = NULL; filepath = kzalloc(PATH_MAX, GFP_KERNEL); if (!filepath) { pr_err("allocate mem for porch failed!\n"); return; } ret = linux_get_file_path(MY_DIR, filepath); if (ret) { pr_err("file not found, use default porch.txt!\n"); snprintf(filepath, PATH_MAX, "%s/%s", MY_DIR, "porch.txt"); }