1+ // file_system.cpp
2+ // Copyright 2014 - 2025 Alex Dixon.
3+ // License: https://github.com/polymonster/pmtech/blob/master/license.md
4+
5+ #include " file_system.h"
6+ #include " memory.h"
7+ #include " os.h"
8+ #include " pen.h"
9+ #include " pen_string.h"
10+
11+ #include < sys/stat.h>
12+ #include < dirent.h>
13+
14+ namespace pen
15+ {
16+ pen_error filesystem_enum_volumes (fs_tree_node& results)
17+ {
18+ // stub
19+ return PEN_ERR_OK;
20+ }
21+
22+ void filesystem_toggle_hidden_files ()
23+ {
24+ // stub
25+ }
26+
27+ bool match_file (struct dirent * ent, s32 num_wildcards, va_list wildcards)
28+ {
29+ return false ;
30+ }
31+
32+ pen_error filesystem_enum_directory (const c8* directory, fs_tree_node& results, s32 num_wildcards, ...)
33+ {
34+ va_list wc;
35+ va_start (wc, num_wildcards);
36+
37+ pen_error res = filesystem_enum_directory (directory, results, num_wildcards, wc);
38+
39+ va_end (wc);
40+
41+ return res;
42+ }
43+
44+ pen_error filesystem_enum_directory (const c8* directory, fs_tree_node& results, s32 num_wildcards, va_list wildcards)
45+ {
46+ DIR* dir;
47+ struct dirent * ent;
48+
49+ u32 num_items = 0 ;
50+ if ((dir = opendir (directory)) != nullptr )
51+ {
52+ while ((ent = readdir (dir)) != nullptr )
53+ {
54+ if (match_file (ent, num_wildcards, wildcards))
55+ {
56+ num_items++;
57+ }
58+ }
59+
60+ closedir (dir);
61+ }
62+
63+ if (num_items == 0 )
64+ {
65+ return PEN_ERR_FILE_NOT_FOUND;
66+ }
67+
68+ if (results.children == nullptr )
69+ {
70+ // alloc new mem
71+ results.children = (fs_tree_node*)pen::memory_alloc (sizeof (fs_tree_node) * num_items);
72+ pen::memory_zero (results.children , sizeof (fs_tree_node) * num_items);
73+ }
74+ else
75+ {
76+ // grow buffer
77+ if (results.num_children < num_items)
78+ {
79+ results.children = (fs_tree_node*)pen::memory_realloc (results.children , sizeof (fs_tree_node) * num_items);
80+ }
81+ }
82+
83+ results.num_children = num_items;
84+
85+ u32 i = 0 ;
86+ if ((dir = opendir (directory)) != nullptr )
87+ {
88+ while ((ent = readdir (dir)) != nullptr )
89+ {
90+ if (match_file (ent, num_wildcards, wildcards))
91+ {
92+ if (results.children [i].name == nullptr )
93+ {
94+ // allocate 1024 file buffer
95+ results.children [i].name = (c8*)pen::memory_alloc (1024 );
96+ pen::memory_zero (results.children [i].name , 1024 );
97+ }
98+
99+ u32 len = pen::string_length (ent->d_name );
100+ len = min<u32 >(len, 1022 );
101+
102+ memcpy (results.children [i].name , ent->d_name , len);
103+ results.children [i].name [len] = ' \0 ' ;
104+
105+ results.children [i].num_children = 0 ;
106+
107+ ++i;
108+ }
109+ }
110+
111+ closedir (dir);
112+ }
113+
114+ return PEN_ERR_OK;
115+ }
116+
117+ pen_error filesystem_enum_free_mem (fs_tree_node& tree)
118+ {
119+ for (s32 i = 0 ; i < tree.num_children ; ++i)
120+ {
121+ filesystem_enum_free_mem (tree.children [i]);
122+ }
123+
124+ pen::memory_free (tree.children );
125+ pen::memory_free (tree.name );
126+
127+ return PEN_ERR_OK;
128+ }
129+
130+ pen_error filesystem_getmtime (const c8* filename, u32 & mtime_out)
131+ {
132+ struct stat st;
133+ if (stat (filename, &st) == 0 ) {
134+ mtime_out = (u32 )st.st_mtime ; // modification time
135+ return PEN_ERR_OK;
136+ }
137+
138+ return PEN_ERR_FILE_NOT_FOUND;
139+ }
140+
141+ const c8** filesystem_get_user_directory (s32& directory_depth)
142+ {
143+ return nullptr ;
144+ }
145+
146+ s32 filesystem_exclude_slash_depth ()
147+ {
148+ // directory depth 0 can be a slash
149+ return 0 ;
150+ }
151+ } // namespace pen
0 commit comments