summaryrefslogtreecommitdiffstats
path: root/glob.rs
blob: 3e249ab1a3dc63deff4b414a001374169bbe8fc0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#[link(name = "glob",
       vers = "0.0.1",
       uuid = "9cb8312d-058c-482f-a0b0-27c48773c74b",
       url  = "https://github.com/doy/rust-glob")];

#[crate_type = "lib"];

use core::libc::{c_char,c_int,c_void,size_t};
use core::path::Path;
use core::unstable::finally::Finally;

pub fn glob (pattern: &str) -> ~[Path] {
    let g = glob_t {
        gl_pathc: 0, gl_pathv: ptr::null(), gl_offs: 0,
        gl_closedir: ptr::null(), gl_readdir: ptr::null(),
        gl_opendir: ptr::null(),
        gl_lstat: ptr::null(), gl_stat: ptr::null(),
    };
    do str::as_c_str(pattern) |c_pattern| {
        unsafe { c::glob(c_pattern, 0, ptr::null(), &g) }
    };
    do(|| {
        let paths = unsafe {
            vec::raw::from_buf_raw(g.gl_pathv, g.gl_pathc as uint)
        };
        do paths.map |&c_str| {
            Path(unsafe { str::raw::from_c_str(c_str) })
        }
    }).finally {
        unsafe { c::globfree(&g) };
    }
}

struct glob_t {
    gl_pathc: size_t,
    gl_pathv: **c_char,
    gl_offs:  size_t,

    // these are nonstandard
    gl_closedir: *c_void,
    gl_readdir:  *c_void,
    gl_opendir:  *c_void,
    gl_lstat:    *c_void,
    gl_stat:     *c_void,
}

extern mod c {
    fn glob(pattern: *c_char, flags: c_int,
            errfunc: *c_void, pglob: *glob_t) -> c_int;
    fn globfree(pglob: *glob_t);
}

#[test]
fn glob_test () {
    let paths = glob("*.rs");
    assert!(paths.len() == 1);
    assert!(paths[0].exists());
    assert!(paths[0].to_str() == ~"glob.rs");
}

#[test]
fn no_glob_test () {
    let paths = glob("*.nonexistent");
    assert!(paths.len() == 0);
}