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.
This commit is contained in:
Marijn Haverbeke 2011-03-10 15:56:51 +01:00 committed by Graydon Hoare
parent 3436979b17
commit c731d625fe
15 changed files with 146 additions and 61 deletions

View file

@ -391,7 +391,7 @@ impure fn eval_crate_directive(parser p,
case (none[filename]) {} case (none[filename]) {}
} }
auto full_path = prefix + std.os.path_sep() + file_path; auto full_path = prefix + std.fs.path_sep() + file_path;
auto start_id = p.next_def_id(); auto start_id = p.next_def_id();
auto p0 = new_parser(p.get_session(), e, start_id, full_path); auto p0 = new_parser(p.get_session(), e, start_id, full_path);
@ -414,7 +414,7 @@ impure fn eval_crate_directive(parser p,
case (none[filename]) {} case (none[filename]) {}
} }
auto full_path = prefix + std.os.path_sep() + path; auto full_path = prefix + std.fs.path_sep() + path;
auto m0 = eval_crate_directives_to_mod(p, e, cdirs, full_path); auto m0 = eval_crate_directives_to_mod(p, e, cdirs, full_path);
auto im = ast.item_mod(id, m0, p.next_def_id()); auto im = ast.item_mod(id, m0, p.next_def_id());
auto i = @spanned(cdir.span, cdir.span, im); auto i = @spanned(cdir.span, cdir.span, im);

View file

@ -2373,7 +2373,7 @@ impure fn parse_crate_directives(parser p, token.token term)
impure fn parse_crate_from_crate_file(parser p) -> @ast.crate { impure fn parse_crate_from_crate_file(parser p) -> @ast.crate {
auto lo = p.get_span(); auto lo = p.get_span();
auto hi = lo; auto hi = lo;
auto prefix = std.path.dirname(lo.filename); auto prefix = std.fs.dirname(lo.filename);
auto cdirs = parse_crate_directives(p, token.EOF); auto cdirs = parse_crate_directives(p, token.EOF);
auto m = eval.eval_crate_directives_to_mod(p, p.get_env(), auto m = eval.eval_crate_directives_to_mod(p, p.get_env(),
cdirs, prefix); cdirs, prefix);

View file

@ -106,6 +106,11 @@ fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
ret rustrt.str_from_vec(v); ret rustrt.str_from_vec(v);
} }
// FIXME temp thing
fn unsafe_from_bytes(vec[u8] v) -> str {
ret rustrt.str_from_vec(v);
}
fn refcount(str s) -> uint { fn refcount(str s) -> uint {
auto r = rustrt.refcount[u8](s); auto r = rustrt.refcount[u8](s);
if (r == dbg.const_refcount) { if (r == dbg.const_refcount) {

37
src/lib/fs.rs Normal file
View file

@ -0,0 +1,37 @@
native "rust" mod rustrt {
fn rust_file_is_dir(str path) -> int;
}
fn path_sep() -> str {
ret _str.unsafe_from_bytes(vec(os_fs.path_sep as u8));
}
type path = str;
fn dirname(path p) -> path {
auto sep = path_sep();
check (_str.byte_len(sep) == 1u);
let int i = _str.rindex(p, sep.(0));
if (i == -1) {
ret p;
}
ret _str.substr(p, 0u, i as uint);
}
impure fn file_is_dir(path p) -> bool {
ret rustrt.rust_file_is_dir(p) != 0;
}
impure fn list_dir(path p) -> vec[str] {
auto pl = _str.byte_len(p);
if (pl == 0u || p.(pl - 1u) as char != os_fs.path_sep) {
p += path_sep();
}
let vec[str] full_paths = vec();
for (str filename in os_fs.list_dir(p)) {
if (!_str.eq(filename, ".")) {if (!_str.eq(filename, "..")) {
full_paths = _vec.push[str](full_paths, p + filename);
}}
}
ret full_paths;
}

View file

@ -86,6 +86,7 @@ tag fileflag {
append; append;
create; create;
truncate; truncate;
none;
} }
state obj fd_buf_writer(int fd, bool must_close) { 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 {
case (append) { fflags |= os.libc_constants.O_APPEND(); } case (append) { fflags |= os.libc_constants.O_APPEND(); }
case (create) { fflags |= os.libc_constants.O_CREAT(); } case (create) { fflags |= os.libc_constants.O_CREAT(); }
case (truncate) { fflags |= os.libc_constants.O_TRUNC(); } case (truncate) { fflags |= os.libc_constants.O_TRUNC(); }
case (none) {}
} }
} }

View file

@ -15,9 +15,10 @@ native mod libc = "libc.so.6" {
fn ungetc(int c, FILE f); fn ungetc(int c, FILE f);
type dir; type dir;
// readdir is a mess; handle via wrapper function in rustrt.
fn opendir(sbuf d) -> dir; fn opendir(sbuf d) -> dir;
fn closedir(dir d) -> int; fn closedir(dir d) -> int;
type dirent;
fn readdir(dir d) -> dirent;
fn getenv(sbuf n) -> sbuf; fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int; fn setenv(sbuf n, sbuf v, int overwrite) -> int;
@ -39,10 +40,6 @@ mod libc_constants {
fn S_IWUSR() -> uint { ret 0x0080u; } fn S_IWUSR() -> uint { ret 0x0080u; }
} }
fn path_sep() -> str {
ret "/";
}
fn exec_suffix() -> str { fn exec_suffix() -> str {
ret ""; ret "";
} }

View file

@ -1,5 +1,4 @@
import _str.sbuf; import libc = posix;
import _vec.vbuf;
native mod libc = "libc.dylib" { native mod libc = "libc.dylib" {
@ -15,9 +14,10 @@ native mod libc = "libc.dylib" {
fn ungetc(int c, FILE f); fn ungetc(int c, FILE f);
type dir; type dir;
// readdir is a mess; handle via wrapper function in rustrt.
fn opendir(sbuf d) -> dir; fn opendir(sbuf d) -> dir;
fn closedir(dir d) -> int; fn closedir(dir d) -> int;
type dirent;
fn readdir(dir d) -> dirent;
fn getenv(sbuf n) -> sbuf; fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int; fn setenv(sbuf n, sbuf v, int overwrite) -> int;
@ -39,10 +39,6 @@ mod libc_constants {
fn S_IWUSR() -> uint { ret 0x0200u; } fn S_IWUSR() -> uint { ret 0x0200u; }
} }
fn path_sep() -> str {
ret "/";
}
fn exec_suffix() -> str { fn exec_suffix() -> str {
ret ""; ret "";
} }

View file

@ -1,21 +0,0 @@
type path = str;
fn dirname(path p) -> path {
auto sep = os.path_sep();
check (_str.byte_len(sep) == 1u);
let int i = _str.rindex(p, sep.(0));
if (i == -1) {
ret p;
}
ret _str.substr(p, 0u, i as uint);
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:

19
src/lib/posix_fs.rs Normal file
View file

@ -0,0 +1,19 @@
native "rust" mod rustrt {
fn rust_dirent_filename(os.libc.dirent ent) -> str;
}
impure fn list_dir(str path) -> vec[str] {
// TODO ensure this is always closed
auto dir = os.libc.opendir(_str.buf(path));
check (dir as uint != 0u);
let vec[str] result = vec();
while (true) {
auto ent = os.libc.readdir(dir);
if (ent as int == 0) {break;}
result = _vec.push[str](result, rustrt.rust_dirent_filename(ent));
}
os.libc.closedir(dir);
ret result;
}
const char path_sep = '/';

View file

@ -26,6 +26,8 @@ mod util;
// Authorize various rule-bendings. // Authorize various rule-bendings.
auth io = unsafe; auth io = unsafe;
auth fs = unsafe;
auth os_fs = unsafe;
auth _str = unsafe; auth _str = unsafe;
auth _vec = unsafe; auth _vec = unsafe;
auth _task = unsafe; auth _task = unsafe;
@ -41,12 +43,17 @@ auth rand.mk_rng = unsafe;
alt (target_os) { alt (target_os) {
case ("win32") { case ("win32") {
mod os = "win32_os.rs"; mod os = "win32_os.rs";
mod os_fs = "win32_fs.rs";
} case ("macos") { } case ("macos") {
mod os = "macos_os.rs"; mod os = "macos_os.rs";
mod os_fs = "posix_fs.rs";
} else { } else {
mod os = "linux_os.rs"; mod os = "linux_os.rs";
mod os_fs = "posix_fs.rs";
} }
} }
mod fs;
// FIXME: parametric // FIXME: parametric
mod map; mod map;
@ -56,7 +63,6 @@ mod rand;
mod dbg; mod dbg;
mod bitv; mod bitv;
mod sort; mod sort;
mod path;
mod sha1; mod sha1;
// Local Variables: // Local Variables:

10
src/lib/win32_fs.rs Normal file
View file

@ -0,0 +1,10 @@
native "rust" mod rustrt {
fn rust_list_files(str path) -> vec[str];
fn rust_file_is_dir(str path) -> int;
}
impure fn list_dir(str path) -> vec[str] {
ret rustrt.rust_list_files(path+"*");
}
const char path_sep = '\\';

View file

@ -29,11 +29,6 @@ mod libc_constants {
fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32 fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32
} }
fn path_sep() -> str {
ret "\\";
}
fn exec_suffix() -> str { fn exec_suffix() -> str {
ret ".exe"; ret ".exe";
} }

View file

@ -1,4 +1,7 @@
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "rust_internal.h" #include "rust_internal.h"
/* Native builtins. */ /* Native builtins. */
@ -150,28 +153,27 @@ vec_print_debug_info(rust_task *task, type_desc *ty, rust_vec *v)
} }
/* Helper for str_alloc and str_from_vec. Returns NULL as failure. */ /* Helper for str_alloc and str_from_vec. Returns NULL as failure. */
static rust_str * static rust_vec*
str_alloc_with_data(rust_task *task, vec_alloc_with_data(rust_task *task,
size_t n_bytes, size_t n_elts,
size_t fill, size_t fill,
uint8_t const *d) size_t elt_size,
void *d)
{ {
rust_dom *dom = task->dom; rust_dom *dom = task->dom;
size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes); size_t alloc = next_power_of_two(sizeof(rust_vec) + (n_elts * elt_size));
void *mem = dom->malloc(alloc, memory_region::LOCAL); void *mem = dom->malloc(alloc, memory_region::LOCAL);
if (!mem) if (!mem) return NULL;
return NULL; return new (mem) rust_vec(dom, alloc, fill * elt_size, (uint8_t*)d);
rust_str *st = new (mem) rust_str(dom, alloc, fill, d);
return st;
} }
extern "C" CDECL rust_str* extern "C" CDECL rust_str*
str_alloc(rust_task *task, size_t n_bytes) str_alloc(rust_task *task, size_t n_bytes)
{ {
rust_str *st = str_alloc_with_data(task, rust_str *st = vec_alloc_with_data(task,
n_bytes + 1, // +1 to fit at least "" n_bytes + 1, // +1 to fit at least ""
1, 1, 1,
(uint8_t const *)""); (void*)"");
if (!st) { if (!st) {
task->fail(2); task->fail(2);
return NULL; return NULL;
@ -195,10 +197,11 @@ extern "C" CDECL rust_str *
str_from_vec(rust_task *task, rust_vec *v) str_from_vec(rust_task *task, rust_vec *v)
{ {
rust_str *st = rust_str *st =
str_alloc_with_data(task, vec_alloc_with_data(task,
v->fill + 1, // +1 to fit at least '\0' v->fill + 1, // +1 to fit at least '\0'
v->fill, v->fill,
v->fill ? (uint8_t const *)v->data : NULL); 1,
v->fill ? (void*)v->data : NULL);
if (!st) { if (!st) {
task->fail(2); task->fail(2);
return NULL; return NULL;
@ -371,6 +374,39 @@ debug_trap(rust_task *task, rust_str *s)
__asm__("int3"); __asm__("int3");
} }
rust_str* c_str_to_rust(rust_task *task, char const *str) {
size_t len = strlen(str) + 1;
return vec_alloc_with_data(task, len, len, 1, (void*)str);
}
#if defined(__WIN32__)
extern "C" CDECL rust_vec*
rust_list_files(rust_task *task, rust_str *path) {
array_list<rust_str*> strings;
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
strings.push(c_str_to_rust(task, FindFileData.cFileName));
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
return vec_alloc_with_data(task, strings.size(), strings.size(),
sizeof(rust_str*), strings.data());
}
#else
extern "C" CDECL rust_str *
rust_dirent_filename(rust_task *task, dirent* ent) {
return c_str_to_rust(task, ent->d_name);
}
#endif
extern "C" CDECL int
rust_file_is_dir(rust_task *task, rust_str *path) {
struct stat buf;
stat((char*)path->data, &buf);
return S_ISDIR(buf.st_mode);
}
// //
// Local Variables: // Local Variables:

View file

@ -177,11 +177,8 @@ rust_vec : public rc_base<rust_vec>
alloc(alloc), alloc(alloc),
fill(fill) fill(fill)
{ {
if (d || fill) { if (d)
I(dom, d);
I(dom, fill);
memcpy(&data[0], d, fill); memcpy(&data[0], d, fill);
}
} }
~rust_vec() {} ~rust_vec() {}
}; };

View file

@ -19,6 +19,7 @@ public:
bool replace(T old_value, T new_value); bool replace(T old_value, T new_value);
int32_t index_of(T value); int32_t index_of(T value);
bool is_empty(); bool is_empty();
T* data();
T & operator[](size_t index); T & operator[](size_t index);
}; };
@ -101,4 +102,9 @@ array_list<T>::is_empty() {
return _size == 0; return _size == 0;
} }
template<typename T> T*
array_list<T>::data() {
return _data;
}
#endif /* ARRAY_LIST_H */ #endif /* ARRAY_LIST_H */