diff options
| author | Marijn Haverbeke <[email protected]> | 2011-03-10 15:56:51 +0100 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-03-14 14:57:13 -0700 |
| commit | c731d625fe5f7626b41c7241893350b8b27b1dbe (patch) | |
| tree | 9b5c8f5071d44d601914fa9ea1e44e07fe6f23db /src | |
| parent | Split trans' collection in two passes. This allows us to handle tags (diff) | |
| download | rust-c731d625fe5f7626b41c7241893350b8b27b1dbe.tar.xz rust-c731d625fe5f7626b41c7241893350b8b27b1dbe.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/front/eval.rs | 4 | ||||
| -rw-r--r-- | src/comp/front/parser.rs | 2 | ||||
| -rw-r--r-- | src/lib/_str.rs | 5 | ||||
| -rw-r--r-- | src/lib/fs.rs | 37 | ||||
| -rw-r--r-- | src/lib/io.rs | 2 | ||||
| -rw-r--r-- | src/lib/linux_os.rs | 7 | ||||
| -rw-r--r-- | src/lib/macos_os.rs | 10 | ||||
| -rw-r--r-- | src/lib/path.rs | 21 | ||||
| -rw-r--r-- | src/lib/posix_fs.rs | 19 | ||||
| -rw-r--r-- | src/lib/std.rc | 10 | ||||
| -rw-r--r-- | src/lib/win32_fs.rs | 10 | ||||
| -rw-r--r-- | src/lib/win32_os.rs | 5 | ||||
| -rw-r--r-- | src/rt/rust_builtin.cpp | 64 | ||||
| -rw-r--r-- | src/rt/rust_util.h | 5 | ||||
| -rw-r--r-- | src/rt/util/array_list.h | 6 |
15 files changed, 146 insertions, 61 deletions
diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs index efa9aa0d..77f3acd1 100644 --- a/src/comp/front/eval.rs +++ b/src/comp/front/eval.rs @@ -391,7 +391,7 @@ impure fn eval_crate_directive(parser p, 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 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]) {} } - 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 im = ast.item_mod(id, m0, p.next_def_id()); auto i = @spanned(cdir.span, cdir.span, im); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 45cec0c0..2ae3b844 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -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 { auto lo = p.get_span(); 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 m = eval.eval_crate_directives_to_mod(p, p.get_env(), cdirs, prefix); diff --git a/src/lib/_str.rs b/src/lib/_str.rs index 3f453349..526dac8f 100644 --- a/src/lib/_str.rs +++ b/src/lib/_str.rs @@ -106,6 +106,11 @@ fn from_bytes(vec[u8] v) : is_utf8(v) -> str { 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 { auto r = rustrt.refcount[u8](s); if (r == dbg.const_refcount) { diff --git a/src/lib/fs.rs b/src/lib/fs.rs new file mode 100644 index 00000000..55f4f979 --- /dev/null +++ b/src/lib/fs.rs @@ -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; +} diff --git a/src/lib/io.rs b/src/lib/io.rs index 34c4a98d..219125c5 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -86,6 +86,7 @@ tag fileflag { append; create; truncate; + none; } 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 (create) { fflags |= os.libc_constants.O_CREAT(); } case (truncate) { fflags |= os.libc_constants.O_TRUNC(); } + case (none) {} } } diff --git a/src/lib/linux_os.rs b/src/lib/linux_os.rs index d5ef2a6b..e05a69b3 100644 --- a/src/lib/linux_os.rs +++ b/src/lib/linux_os.rs @@ -15,9 +15,10 @@ native mod libc = "libc.so.6" { fn ungetc(int c, FILE f); type dir; - // readdir is a mess; handle via wrapper function in rustrt. fn opendir(sbuf d) -> dir; fn closedir(dir d) -> int; + type dirent; + fn readdir(dir d) -> dirent; fn getenv(sbuf n) -> sbuf; fn setenv(sbuf n, sbuf v, int overwrite) -> int; @@ -39,10 +40,6 @@ mod libc_constants { fn S_IWUSR() -> uint { ret 0x0080u; } } -fn path_sep() -> str { - ret "/"; -} - fn exec_suffix() -> str { ret ""; } diff --git a/src/lib/macos_os.rs b/src/lib/macos_os.rs index 53a66b56..3dc63bad 100644 --- a/src/lib/macos_os.rs +++ b/src/lib/macos_os.rs @@ -1,5 +1,4 @@ -import _str.sbuf; -import _vec.vbuf; +import libc = posix; native mod libc = "libc.dylib" { @@ -15,9 +14,10 @@ native mod libc = "libc.dylib" { fn ungetc(int c, FILE f); type dir; - // readdir is a mess; handle via wrapper function in rustrt. fn opendir(sbuf d) -> dir; fn closedir(dir d) -> int; + type dirent; + fn readdir(dir d) -> dirent; fn getenv(sbuf n) -> sbuf; fn setenv(sbuf n, sbuf v, int overwrite) -> int; @@ -39,10 +39,6 @@ mod libc_constants { fn S_IWUSR() -> uint { ret 0x0200u; } } -fn path_sep() -> str { - ret "/"; -} - fn exec_suffix() -> str { ret ""; } diff --git a/src/lib/path.rs b/src/lib/path.rs deleted file mode 100644 index 9cda93d6..00000000 --- a/src/lib/path.rs +++ /dev/null @@ -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: diff --git a/src/lib/posix_fs.rs b/src/lib/posix_fs.rs new file mode 100644 index 00000000..05366a15 --- /dev/null +++ b/src/lib/posix_fs.rs @@ -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 = '/'; diff --git a/src/lib/std.rc b/src/lib/std.rc index 4ad422a3..8098a4e9 100644 --- a/src/lib/std.rc +++ b/src/lib/std.rc @@ -26,6 +26,8 @@ mod util; // Authorize various rule-bendings. auth io = unsafe; +auth fs = unsafe; +auth os_fs = unsafe; auth _str = unsafe; auth _vec = unsafe; auth _task = unsafe; @@ -41,12 +43,17 @@ auth rand.mk_rng = unsafe; alt (target_os) { case ("win32") { mod os = "win32_os.rs"; + mod os_fs = "win32_fs.rs"; } case ("macos") { mod os = "macos_os.rs"; + mod os_fs = "posix_fs.rs"; } else { mod os = "linux_os.rs"; + mod os_fs = "posix_fs.rs"; } - } +} +mod fs; + // FIXME: parametric mod map; @@ -56,7 +63,6 @@ mod rand; mod dbg; mod bitv; mod sort; -mod path; mod sha1; // Local Variables: diff --git a/src/lib/win32_fs.rs b/src/lib/win32_fs.rs new file mode 100644 index 00000000..641ef33e --- /dev/null +++ b/src/lib/win32_fs.rs @@ -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 = '\\'; diff --git a/src/lib/win32_os.rs b/src/lib/win32_os.rs index 9f9ec2c2..0c6a23a6 100644 --- a/src/lib/win32_os.rs +++ b/src/lib/win32_os.rs @@ -29,11 +29,6 @@ mod libc_constants { fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32 } - -fn path_sep() -> str { - ret "\\"; -} - fn exec_suffix() -> str { ret ".exe"; } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index a859c7b9..250280f2 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -1,4 +1,7 @@ +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> #include "rust_internal.h" /* 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. */ -static rust_str * -str_alloc_with_data(rust_task *task, - size_t n_bytes, +static rust_vec* +vec_alloc_with_data(rust_task *task, + size_t n_elts, size_t fill, - uint8_t const *d) + size_t elt_size, + void *d) { 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); - if (!mem) - return NULL; - rust_str *st = new (mem) rust_str(dom, alloc, fill, d); - return st; + if (!mem) return NULL; + return new (mem) rust_vec(dom, alloc, fill * elt_size, (uint8_t*)d); } extern "C" CDECL rust_str* 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 "" - 1, - (uint8_t const *)""); + 1, 1, + (void*)""); if (!st) { task->fail(2); return NULL; @@ -195,10 +197,11 @@ extern "C" CDECL rust_str * str_from_vec(rust_task *task, rust_vec *v) { rust_str *st = - str_alloc_with_data(task, + vec_alloc_with_data(task, v->fill + 1, // +1 to fit at least '\0' v->fill, - v->fill ? (uint8_t const *)v->data : NULL); + 1, + v->fill ? (void*)v->data : NULL); if (!st) { task->fail(2); return NULL; @@ -371,6 +374,39 @@ debug_trap(rust_task *task, rust_str *s) __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: diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index 03b7766d..5f13a3c8 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -177,11 +177,8 @@ rust_vec : public rc_base<rust_vec> alloc(alloc), fill(fill) { - if (d || fill) { - I(dom, d); - I(dom, fill); + if (d) memcpy(&data[0], d, fill); - } } ~rust_vec() {} }; diff --git a/src/rt/util/array_list.h b/src/rt/util/array_list.h index d44111e8..9ad4b208 100644 --- a/src/rt/util/array_list.h +++ b/src/rt/util/array_list.h @@ -19,6 +19,7 @@ public: bool replace(T old_value, T new_value); int32_t index_of(T value); bool is_empty(); + T* data(); T & operator[](size_t index); }; @@ -101,4 +102,9 @@ array_list<T>::is_empty() { return _size == 0; } +template<typename T> T* +array_list<T>::data() { + return _data; +} + #endif /* ARRAY_LIST_H */ |