Skip to content

Commit 2330c96

Browse files
committed
Add basic file-system functionality
std.fs.list_dir will list the files in a directory, std.fs.file_is_dir will, given a pathname, determine whether it is a directory or not.
1 parent 8e8c336 commit 2330c96

File tree

8 files changed

+109
-3
lines changed

8 files changed

+109
-3
lines changed

src/lib/_str.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
106106
ret rustrt.str_from_vec(v);
107107
}
108108

109+
// FIXME temp thing
110+
fn unsafe_from_bytes(vec[u8] v) -> str {
111+
ret rustrt.str_from_vec(v);
112+
}
113+
109114
fn refcount(str s) -> uint {
110115
auto r = rustrt.refcount[u8](s);
111116
if (r == dbg.const_refcount) {

src/lib/fs.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
native "rust" mod rustrt {
2+
fn rust_file_is_dir(str path) -> int;
3+
}
4+
5+
impure fn file_is_dir(str path) -> bool {
6+
ret rustrt.rust_file_is_dir(path) != 0;
7+
}
8+
9+
impure fn list_dir(str path) -> vec[str] {
10+
if (path.(_str.byte_len(path)-1u) as char != os_fs.path_sep) {
11+
path += _str.unsafe_from_bytes(vec(os_fs.path_sep as u8));
12+
}
13+
let vec[str] full_paths = vec();
14+
for (str filename in os_fs.list_dir(path)) {
15+
if (!_str.eq(filename, ".")) {if (!_str.eq(filename, "..")) {
16+
full_paths = _vec.push[str](full_paths, path + filename);
17+
}}
18+
}
19+
ret full_paths;
20+
}

src/lib/linux_os.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ native mod libc = "libc.so.6" {
1515
fn ungetc(int c, FILE f);
1616

1717
type dir;
18-
// readdir is a mess; handle via wrapper function in rustrt.
1918
fn opendir(sbuf d) -> dir;
2019
fn closedir(dir d) -> int;
20+
type dirent;
21+
fn readdir(dir d) -> dirent;
2122

2223
fn getenv(sbuf n) -> sbuf;
2324
fn setenv(sbuf n, sbuf v, int overwrite) -> int;

src/lib/macos_os.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ native mod libc = "libc.dylib" {
1515
fn ungetc(int c, FILE f);
1616

1717
type dir;
18-
// readdir is a mess; handle via wrapper function in rustrt.
1918
fn opendir(sbuf d) -> dir;
2019
fn closedir(dir d) -> int;
20+
type dirent;
21+
fn readdir(dir d) -> dirent;
2122

2223
fn getenv(sbuf n) -> sbuf;
2324
fn setenv(sbuf n, sbuf v, int overwrite) -> int;

src/lib/posix_fs.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
native "rust" mod rustrt {
2+
fn rust_dirent_filename(os.libc.dirent ent) -> str;
3+
}
4+
5+
impure fn list_dir(str path) -> vec[str] {
6+
// TODO ensure this is always closed
7+
auto dir = os.libc.opendir(_str.buf(path));
8+
check (dir as uint != 0u);
9+
let vec[str] result = vec();
10+
while (true) {
11+
auto ent = os.libc.readdir(dir);
12+
if (ent as int == 0) {break;}
13+
result = _vec.push[str](result, rustrt.rust_dirent_filename(ent));
14+
}
15+
os.libc.closedir(dir);
16+
ret result;
17+
}
18+
19+
const char path_sep = '/';

src/lib/std.rc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ mod util;
2626
// Authorize various rule-bendings.
2727

2828
auth io = unsafe;
29+
auth fs = unsafe;
30+
auth os_fs = unsafe;
2931
auth _str = unsafe;
3032
auth _vec = unsafe;
3133
auth _task = unsafe;
@@ -41,12 +43,17 @@ auth rand.mk_rng = unsafe;
4143
alt (target_os) {
4244
case ("win32") {
4345
mod os = "win32_os.rs";
46+
mod os_fs = "win32_fs.rs";
4447
} case ("macos") {
4548
mod os = "macos_os.rs";
49+
mod os_fs = "posix_fs.rs";
4650
} else {
4751
mod os = "linux_os.rs";
52+
mod os_fs = "posix_fs.rs";
4853
}
49-
}
54+
}
55+
mod fs;
56+
5057

5158
// FIXME: parametric
5259
mod map;

src/lib/win32_fs.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
native "rust" mod rustrt {
2+
fn rust_list_files[T,U](str path) -> vec[str];
3+
fn rust_file_is_dir(str path) -> int;
4+
}
5+
6+
impure fn list_dir(str path) -> vec[str] {
7+
ret rustrt.rust_list_files[vec[str],str](path+"*");
8+
}
9+
10+
const char path_sep = '\\';

src/rt/rust_builtin.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11

2+
#include <dirent.h>
3+
#include <sys/types.h>
4+
#include <sys/stat.h>
25
#include "rust_internal.h"
36

47
/* Native builtins. */
@@ -371,6 +374,46 @@ debug_trap(rust_task *task, rust_str *s)
371374
__asm__("int3");
372375
}
373376

377+
rust_str* c_str_to_rust(rust_task *task, char const *str) {
378+
size_t len = strlen(str) + 1;
379+
return str_alloc_with_data(task, len, len, (uint8_t const *)str);
380+
}
381+
382+
#if defined(__WIN32__)
383+
extern "C" CDECL rust_vec*
384+
rust_list_files(rust_task *task, type_desc *vec_desc,
385+
type_desc *str_desc, rust_str *path) {
386+
rust_str* strings[200];
387+
size_t pos = 0;
388+
WIN32_FIND_DATA FindFileData;
389+
HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData);
390+
if (hFind != INVALID_HANDLE_VALUE) {
391+
strings[pos++] = c_str_to_rust(task, FindFileData.cFileName);
392+
while (FindNextFile(hFind, &FindFileData)) {
393+
strings[pos++] = c_str_to_rust(task, FindFileData.cFileName);
394+
}
395+
FindClose(hFind);
396+
}
397+
rust_vec* result = vec_alloc(task, vec_desc, str_desc, pos);
398+
for (size_t i = 0; i < pos; ++i) {
399+
*(rust_str**)vec_buf(task, str_desc, result, i) = strings[i];
400+
}
401+
vec_len_set(task, str_desc, result, pos);
402+
return result;
403+
}
404+
#else
405+
extern "C" CDECL rust_str *
406+
rust_dirent_filename(rust_task *task, dirent* ent) {
407+
return c_str_to_rust(task, ent->d_name);
408+
}
409+
#endif
410+
411+
extern "C" CDECL int
412+
rust_file_is_dir(rust_task *task, rust_str *path) {
413+
struct stat buf;
414+
stat((char*)path->data, &buf);
415+
return S_ISDIR(buf.st_mode);
416+
}
374417

375418
//
376419
// Local Variables:

0 commit comments

Comments
 (0)