Skip to content

Commit c731d62

Browse files
marijnhgraydon
authored andcommitted
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 3436979 commit c731d62

15 files changed

+146
-61
lines changed

src/comp/front/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ impure fn eval_crate_directive(parser p,
391391
case (none[filename]) {}
392392
}
393393

394-
auto full_path = prefix + std.os.path_sep() + file_path;
394+
auto full_path = prefix + std.fs.path_sep() + file_path;
395395

396396
auto start_id = p.next_def_id();
397397
auto p0 = new_parser(p.get_session(), e, start_id, full_path);
@@ -414,7 +414,7 @@ impure fn eval_crate_directive(parser p,
414414
case (none[filename]) {}
415415
}
416416

417-
auto full_path = prefix + std.os.path_sep() + path;
417+
auto full_path = prefix + std.fs.path_sep() + path;
418418
auto m0 = eval_crate_directives_to_mod(p, e, cdirs, full_path);
419419
auto im = ast.item_mod(id, m0, p.next_def_id());
420420
auto i = @spanned(cdir.span, cdir.span, im);

src/comp/front/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2373,7 +2373,7 @@ impure fn parse_crate_directives(parser p, token.token term)
23732373
impure fn parse_crate_from_crate_file(parser p) -> @ast.crate {
23742374
auto lo = p.get_span();
23752375
auto hi = lo;
2376-
auto prefix = std.path.dirname(lo.filename);
2376+
auto prefix = std.fs.dirname(lo.filename);
23772377
auto cdirs = parse_crate_directives(p, token.EOF);
23782378
auto m = eval.eval_crate_directives_to_mod(p, p.get_env(),
23792379
cdirs, prefix);

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: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
native "rust" mod rustrt {
2+
fn rust_file_is_dir(str path) -> int;
3+
}
4+
5+
fn path_sep() -> str {
6+
ret _str.unsafe_from_bytes(vec(os_fs.path_sep as u8));
7+
}
8+
9+
type path = str;
10+
11+
fn dirname(path p) -> path {
12+
auto sep = path_sep();
13+
check (_str.byte_len(sep) == 1u);
14+
let int i = _str.rindex(p, sep.(0));
15+
if (i == -1) {
16+
ret p;
17+
}
18+
ret _str.substr(p, 0u, i as uint);
19+
}
20+
21+
impure fn file_is_dir(path p) -> bool {
22+
ret rustrt.rust_file_is_dir(p) != 0;
23+
}
24+
25+
impure fn list_dir(path p) -> vec[str] {
26+
auto pl = _str.byte_len(p);
27+
if (pl == 0u || p.(pl - 1u) as char != os_fs.path_sep) {
28+
p += path_sep();
29+
}
30+
let vec[str] full_paths = vec();
31+
for (str filename in os_fs.list_dir(p)) {
32+
if (!_str.eq(filename, ".")) {if (!_str.eq(filename, "..")) {
33+
full_paths = _vec.push[str](full_paths, p + filename);
34+
}}
35+
}
36+
ret full_paths;
37+
}

src/lib/io.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ tag fileflag {
8686
append;
8787
create;
8888
truncate;
89+
none;
8990
}
9091

9192
state obj fd_buf_writer(int fd, bool must_close) {
@@ -120,6 +121,7 @@ fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
120121
case (append) { fflags |= os.libc_constants.O_APPEND(); }
121122
case (create) { fflags |= os.libc_constants.O_CREAT(); }
122123
case (truncate) { fflags |= os.libc_constants.O_TRUNC(); }
124+
case (none) {}
123125
}
124126
}
125127

src/lib/linux_os.rs

Lines changed: 2 additions & 5 deletions
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;
@@ -39,10 +40,6 @@ mod libc_constants {
3940
fn S_IWUSR() -> uint { ret 0x0080u; }
4041
}
4142

42-
fn path_sep() -> str {
43-
ret "/";
44-
}
45-
4643
fn exec_suffix() -> str {
4744
ret "";
4845
}

src/lib/macos_os.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import _str.sbuf;
2-
import _vec.vbuf;
1+
import libc = posix;
32

43
native mod libc = "libc.dylib" {
54

@@ -15,9 +14,10 @@ native mod libc = "libc.dylib" {
1514
fn ungetc(int c, FILE f);
1615

1716
type dir;
18-
// readdir is a mess; handle via wrapper function in rustrt.
1917
fn opendir(sbuf d) -> dir;
2018
fn closedir(dir d) -> int;
19+
type dirent;
20+
fn readdir(dir d) -> dirent;
2121

2222
fn getenv(sbuf n) -> sbuf;
2323
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
@@ -39,10 +39,6 @@ mod libc_constants {
3939
fn S_IWUSR() -> uint { ret 0x0200u; }
4040
}
4141

42-
fn path_sep() -> str {
43-
ret "/";
44-
}
45-
4642
fn exec_suffix() -> str {
4743
ret "";
4844
}

src/lib/path.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

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 & 2 deletions
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;
@@ -56,7 +63,6 @@ mod rand;
5663
mod dbg;
5764
mod bitv;
5865
mod sort;
59-
mod path;
6066
mod sha1;
6167

6268
// Local Variables:

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(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(path+"*");
8+
}
9+
10+
const char path_sep = '\\';

src/lib/win32_os.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ mod libc_constants {
2929
fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32
3030
}
3131

32-
33-
fn path_sep() -> str {
34-
ret "\\";
35-
}
36-
3732
fn exec_suffix() -> str {
3833
ret ".exe";
3934
}

src/rt/rust_builtin.cpp

Lines changed: 50 additions & 14 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. */
@@ -150,28 +153,27 @@ vec_print_debug_info(rust_task *task, type_desc *ty, rust_vec *v)
150153
}
151154

152155
/* Helper for str_alloc and str_from_vec. Returns NULL as failure. */
153-
static rust_str *
154-
str_alloc_with_data(rust_task *task,
155-
size_t n_bytes,
156+
static rust_vec*
157+
vec_alloc_with_data(rust_task *task,
158+
size_t n_elts,
156159
size_t fill,
157-
uint8_t const *d)
160+
size_t elt_size,
161+
void *d)
158162
{
159163
rust_dom *dom = task->dom;
160-
size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes);
164+
size_t alloc = next_power_of_two(sizeof(rust_vec) + (n_elts * elt_size));
161165
void *mem = dom->malloc(alloc, memory_region::LOCAL);
162-
if (!mem)
163-
return NULL;
164-
rust_str *st = new (mem) rust_str(dom, alloc, fill, d);
165-
return st;
166+
if (!mem) return NULL;
167+
return new (mem) rust_vec(dom, alloc, fill * elt_size, (uint8_t*)d);
166168
}
167169

168170
extern "C" CDECL rust_str*
169171
str_alloc(rust_task *task, size_t n_bytes)
170172
{
171-
rust_str *st = str_alloc_with_data(task,
173+
rust_str *st = vec_alloc_with_data(task,
172174
n_bytes + 1, // +1 to fit at least ""
173-
1,
174-
(uint8_t const *)"");
175+
1, 1,
176+
(void*)"");
175177
if (!st) {
176178
task->fail(2);
177179
return NULL;
@@ -195,10 +197,11 @@ extern "C" CDECL rust_str *
195197
str_from_vec(rust_task *task, rust_vec *v)
196198
{
197199
rust_str *st =
198-
str_alloc_with_data(task,
200+
vec_alloc_with_data(task,
199201
v->fill + 1, // +1 to fit at least '\0'
200202
v->fill,
201-
v->fill ? (uint8_t const *)v->data : NULL);
203+
1,
204+
v->fill ? (void*)v->data : NULL);
202205
if (!st) {
203206
task->fail(2);
204207
return NULL;
@@ -371,6 +374,39 @@ 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 vec_alloc_with_data(task, len, len, 1, (void*)str);
380+
}
381+
382+
#if defined(__WIN32__)
383+
extern "C" CDECL rust_vec*
384+
rust_list_files(rust_task *task, rust_str *path) {
385+
array_list<rust_str*> strings;
386+
WIN32_FIND_DATA FindFileData;
387+
HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData);
388+
if (hFind != INVALID_HANDLE_VALUE) {
389+
do {
390+
strings.push(c_str_to_rust(task, FindFileData.cFileName));
391+
} while (FindNextFile(hFind, &FindFileData));
392+
FindClose(hFind);
393+
}
394+
return vec_alloc_with_data(task, strings.size(), strings.size(),
395+
sizeof(rust_str*), strings.data());
396+
}
397+
#else
398+
extern "C" CDECL rust_str *
399+
rust_dirent_filename(rust_task *task, dirent* ent) {
400+
return c_str_to_rust(task, ent->d_name);
401+
}
402+
#endif
403+
404+
extern "C" CDECL int
405+
rust_file_is_dir(rust_task *task, rust_str *path) {
406+
struct stat buf;
407+
stat((char*)path->data, &buf);
408+
return S_ISDIR(buf.st_mode);
409+
}
374410

375411
//
376412
// Local Variables:

src/rt/rust_util.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,8 @@ rust_vec : public rc_base<rust_vec>
177177
alloc(alloc),
178178
fill(fill)
179179
{
180-
if (d || fill) {
181-
I(dom, d);
182-
I(dom, fill);
180+
if (d)
183181
memcpy(&data[0], d, fill);
184-
}
185182
}
186183
~rust_vec() {}
187184
};

src/rt/util/array_list.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ template<typename T> class array_list {
1919
bool replace(T old_value, T new_value);
2020
int32_t index_of(T value);
2121
bool is_empty();
22+
T* data();
2223
T & operator[](size_t index);
2324
};
2425

@@ -101,4 +102,9 @@ array_list<T>::is_empty() {
101102
return _size == 0;
102103
}
103104

105+
template<typename T> T*
106+
array_list<T>::data() {
107+
return _data;
108+
}
109+
104110
#endif /* ARRAY_LIST_H */

0 commit comments

Comments
 (0)