backported more fixes from 256boss
[bootcensus] / src / libc / dirent.c
1 /*
2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018-2019  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include "dirent.h"
22 #include "fs.h"
23
24 struct DIR {
25         struct fs_node *fsn;
26         struct dirent dent;
27 };
28
29 DIR *opendir(const char *path)
30 {
31         DIR *dir;
32         struct fs_node *node;
33
34         if(!path) {
35                 errno = EINVAL;
36                 return 0;
37         }
38
39         if(!(node = fs_open(path, 0))) {
40                 errno = ENOENT;
41                 return 0;
42         }
43         if(node->type != FSNODE_DIR) {
44                 errno = ENOTDIR;
45                 fs_close(node);
46                 return 0;
47         }
48
49         if(!(dir = malloc(sizeof *dir))) {
50                 errno = ENOMEM;
51                 fs_close(node);
52                 return 0;
53         }
54         dir->fsn = node;
55
56         return dir;
57 }
58
59 int closedir(DIR *dir)
60 {
61         if(!dir) {
62                 errno = EINVAL;
63                 return -1;
64         }
65         fs_close(dir->fsn);
66         free(dir);
67         return 0;
68 }
69
70 void rewinddir(DIR *dir)
71 {
72         if(!dir) {
73                 errno = EINVAL;
74                 return;
75         }
76         fs_rewinddir(dir->fsn);
77 }
78
79 struct dirent *readdir(DIR *dir)
80 {
81         struct fs_dirent *fsdent;
82
83         if(!dir) {
84                 errno = EINVAL;
85                 return 0;
86         }
87         if(!(fsdent = fs_readdir(dir->fsn))) {
88                 return 0;
89         }
90
91         strcpy(dir->dent.d_name, fsdent->name);
92         dir->dent.d_type = fsdent->type == FSNODE_DIR ? DT_DIR : DT_REG;
93         dir->dent.d_fsize = fsdent->fsize;
94         return &dir->dent;
95 }