Added cross-platform fsync api to io; win32 impl needs to be refined
No tests, need mktmpfile first
This commit is contained in:
parent
46e5e2f685
commit
21c69d4ba4
@ -25,6 +25,9 @@ type buf_reader =
|
||||
fn eof() -> bool;
|
||||
fn seek(int, seek_style);
|
||||
fn tell() -> uint;
|
||||
// Needed on readers in case one needs to flush metadata
|
||||
// changes (atime)
|
||||
fn fsync(level: fsync::level) -> int;
|
||||
};
|
||||
|
||||
|
||||
@ -58,7 +61,9 @@ fn convert_whence(whence: seek_style) -> i32 {
|
||||
};
|
||||
}
|
||||
|
||||
resource FILE_res(f: os::libc::FILE) { os::libc::fclose(f); }
|
||||
resource FILE_res(f: os::libc::FILE) {
|
||||
os::libc::fclose(f);
|
||||
}
|
||||
|
||||
obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
|
||||
fn read(len: uint) -> [u8] unsafe {
|
||||
@ -76,6 +81,9 @@ obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
|
||||
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0i32);
|
||||
}
|
||||
fn tell() -> uint { ret os::libc::ftell(f) as uint; }
|
||||
fn fsync(level: fsync::level) -> int {
|
||||
ret os::fsync_fd(os::libc::fileno(f), level) as int;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -219,6 +227,7 @@ obj byte_buf_reader(bbuf: byte_buf) {
|
||||
bbuf.pos = seek_in_buf(offset, pos, len, whence);
|
||||
}
|
||||
fn tell() -> uint { ret bbuf.pos; }
|
||||
fn fsync(_level: fsync::level) -> int { ret 0; }
|
||||
}
|
||||
|
||||
fn new_byte_buf_reader(buf: [u8]) -> buf_reader {
|
||||
@ -242,6 +251,8 @@ type buf_writer =
|
||||
fn write([u8]);
|
||||
fn seek(int, seek_style);
|
||||
fn tell() -> uint;
|
||||
fn flush() -> int;
|
||||
fn fsync(level: fsync::level) -> int;
|
||||
};
|
||||
|
||||
obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
|
||||
@ -255,6 +266,10 @@ obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
|
||||
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0i32);
|
||||
}
|
||||
fn tell() -> uint { ret os::libc::ftell(f) as uint; }
|
||||
fn flush() -> int { ret os::libc::fflush(f) as int; }
|
||||
fn fsync(level: fsync::level) -> int {
|
||||
ret os::fsync_fd(os::libc::fileno(f), level) as int;
|
||||
}
|
||||
}
|
||||
|
||||
resource fd_res(fd: fd_t) { os::libc::close(fd); }
|
||||
@ -283,6 +298,12 @@ obj fd_buf_writer(fd: fd_t, res: option::t<@fd_res>) {
|
||||
log_err "need 64-bit native calls for tell, sorry";
|
||||
fail;
|
||||
}
|
||||
|
||||
fn flush() -> int { ret 0; }
|
||||
|
||||
fn fsync(level: fsync::level) -> int {
|
||||
ret os::fsync_fd(fd, level) as int;
|
||||
}
|
||||
}
|
||||
|
||||
fn file_buf_writer(path: str,
|
||||
@ -433,6 +454,8 @@ obj byte_buf_writer(buf: mutable_byte_buf) {
|
||||
buf.pos = seek_in_buf(offset, pos, len, whence);
|
||||
}
|
||||
fn tell() -> uint { ret buf.pos; }
|
||||
fn flush() -> int { ret 0; }
|
||||
fn fsync(_level: fsync::level) -> int { ret 0; }
|
||||
}
|
||||
|
||||
fn string_writer() -> str_writer {
|
||||
@ -477,6 +500,75 @@ fn read_whole_file(file: str) -> result::t<[u8], str> {
|
||||
})
|
||||
}
|
||||
|
||||
// fsync related
|
||||
|
||||
mod fsync {
|
||||
|
||||
tag level {
|
||||
// whatever fsync does on that platform
|
||||
fsync;
|
||||
|
||||
// fdatasync on linux, similiar or more on other platforms
|
||||
fdatasync;
|
||||
|
||||
// full fsync
|
||||
//
|
||||
// You must additionally sync the parent directory as well!
|
||||
fullfsync;
|
||||
}
|
||||
|
||||
|
||||
// Resource of artifacts that need to fsync on destruction
|
||||
resource res<t>(arg: arg<t>) {
|
||||
alt arg.opt_level {
|
||||
option::none::<level>. { }
|
||||
option::some::<level>(level) {
|
||||
// fail hard if not succesful
|
||||
assert(arg.fsync_fn(arg.val, level) != -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type arg<t> = {
|
||||
val: t,
|
||||
opt_level: option::t<level>,
|
||||
fsync_fn: fn(t, level) -> int
|
||||
};
|
||||
|
||||
// fsync file after executing blk
|
||||
// FIXME find better way to create resources within lifetime of outer res
|
||||
fn FILE_res_sync(&&file: FILE_res, opt_level: option::t<level>,
|
||||
blk: block(&&res<os::libc::FILE>)) {
|
||||
blk(res({
|
||||
val: *file, opt_level: opt_level,
|
||||
fsync_fn: fn(&&file: os::libc::FILE, l: level) -> int {
|
||||
ret os::fsync_fd(os::libc::fileno(file), l) as int;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// fsync fd after executing blk
|
||||
fn fd_res_sync(&&fd: fd_res, opt_level: option::t<level>,
|
||||
blk: block(&&res<fd_t>)) {
|
||||
blk(res({
|
||||
val: *fd, opt_level: opt_level,
|
||||
fsync_fn: fn(&&fd: fd_t, l: level) -> int {
|
||||
ret os::fsync_fd(fd, l) as int;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Type of objects that may want to fsync
|
||||
type t = obj { fn fsync(l: level) -> int; };
|
||||
|
||||
// Call o.fsync after executing blk
|
||||
fn obj_sync(&&o: t, opt_level: option::t<level>, blk: block(&&res<t>)) {
|
||||
blk(res({
|
||||
val: o, opt_level: opt_level,
|
||||
fsync_fn: fn(&&o: t, l: level) -> int { ret o.fsync(l); }
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
@ -18,6 +18,7 @@ export exec_suffix;
|
||||
export target_os;
|
||||
export dylib_filename;
|
||||
export get_exe_path;
|
||||
export fsync_fd;
|
||||
|
||||
// FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
|
||||
// by https://github.com/graydon/rust/issues#issue/268
|
||||
@ -35,6 +36,10 @@ native mod libc {
|
||||
fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
|
||||
fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
|
||||
fn fclose(f: FILE);
|
||||
fn fflush(f: FILE) -> c_int;
|
||||
fn fsync(fd: fd_t) -> c_int;
|
||||
fn fdatasync(fd: fd_t) -> c_int;
|
||||
fn fileno(f: FILE) -> fd_t;
|
||||
fn fgetc(f: FILE) -> c_int;
|
||||
fn ungetc(c: c_int, f: FILE);
|
||||
fn feof(f: FILE) -> c_int;
|
||||
@ -89,6 +94,13 @@ fn fclose(file: libc::FILE) {
|
||||
libc::fclose(file)
|
||||
}
|
||||
|
||||
fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
|
||||
alt level {
|
||||
io::fsync::fsync. | io::fsync::fullfsync. { ret libc::fsync(fd); }
|
||||
io::fsync::fdatasync. { ret libc::fdatasync(fd); }
|
||||
}
|
||||
}
|
||||
|
||||
fn waitpid(pid: pid_t) -> i32 {
|
||||
let status = 0i32;
|
||||
assert (os::libc::waitpid(pid, status, 0i32) != -1i32);
|
||||
|
@ -12,6 +12,7 @@ export exec_suffix;
|
||||
export target_os;
|
||||
export dylib_filename;
|
||||
export get_exe_path;
|
||||
export fsync_fd;
|
||||
|
||||
// FIXME Refactor into unix_os module or some such. Doesn't
|
||||
// seem to work right now.
|
||||
@ -28,6 +29,9 @@ native mod libc {
|
||||
type FILE;
|
||||
fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
|
||||
fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
|
||||
fn fflush(f: FILE) -> c_int;
|
||||
fn fsync(fd: fd_t) -> c_int;
|
||||
fn fileno(f: FILE) -> fd_t;
|
||||
fn fclose(f: FILE);
|
||||
fn fgetc(f: FILE) -> c_int;
|
||||
fn ungetc(c: c_int, f: FILE);
|
||||
@ -47,21 +51,26 @@ native mod libc {
|
||||
fn mkdir(s: str::sbuf, mode: c_int) -> c_int;
|
||||
fn rmdir(s: str::sbuf) -> c_int;
|
||||
fn chdir(s: str::sbuf) -> c_int;
|
||||
|
||||
// FIXME: Needs varags
|
||||
fn fcntl(fd: fd_t, cmd: c_int) -> c_int;
|
||||
}
|
||||
|
||||
mod libc_constants {
|
||||
const O_RDONLY: c_int = 0i32;
|
||||
const O_WRONLY: c_int = 1i32;
|
||||
const O_RDWR: c_int = 2i32;
|
||||
const O_APPEND: c_int = 8i32;
|
||||
const O_CREAT: c_int = 512i32;
|
||||
const O_EXCL: c_int = 2048i32;
|
||||
const O_TRUNC: c_int = 1024i32;
|
||||
const O_TEXT: c_int = 0i32; // nonexistent in darwin libc
|
||||
const O_BINARY: c_int = 0i32; // nonexistent in darwin libc
|
||||
const O_RDONLY: c_int = 0i32;
|
||||
const O_WRONLY: c_int = 1i32;
|
||||
const O_RDWR: c_int = 2i32;
|
||||
const O_APPEND: c_int = 8i32;
|
||||
const O_CREAT: c_int = 512i32;
|
||||
const O_EXCL: c_int = 2048i32;
|
||||
const O_TRUNC: c_int = 1024i32;
|
||||
const O_TEXT: c_int = 0i32; // nonexistent in darwin libc
|
||||
const O_BINARY: c_int = 0i32; // nonexistent in darwin libc
|
||||
|
||||
const S_IRUSR: unsigned = 256u32;
|
||||
const S_IWUSR: unsigned = 128u32;
|
||||
const S_IRUSR: unsigned = 256u32;
|
||||
const S_IWUSR: unsigned = 128u32;
|
||||
|
||||
const F_FULLFSYNC: c_int = 51i32;
|
||||
}
|
||||
|
||||
fn pipe() -> {in: fd_t, out: fd_t} {
|
||||
@ -88,6 +97,19 @@ fn waitpid(pid: pid_t) -> i32 {
|
||||
ret status;
|
||||
}
|
||||
|
||||
fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
|
||||
alt level {
|
||||
io::fsync::fsync. { ret libc::fsync(fd); }
|
||||
_ {
|
||||
// According to man fnctl, the ok retval is only specified to be !=-1
|
||||
if (libc::fcntl(libc_constants::F_FULLFSYNC, fd) == -1 as c_int)
|
||||
{ ret -1 as c_int; }
|
||||
else
|
||||
{ ret 0 as c_int; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[abi = "cdecl"]
|
||||
native mod rustrt {
|
||||
fn rust_getcwd() -> str;
|
||||
|
@ -15,6 +15,9 @@ native mod libc {
|
||||
fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
|
||||
fn _fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
|
||||
fn fclose(f: FILE);
|
||||
fn fflush(f: FILE) -> c_int;
|
||||
fn fsync(fd: fd_t) -> c_int;
|
||||
fn fileno(f: FILE) -> fd_t;
|
||||
fn fgetc(f: FILE) -> c_int;
|
||||
fn ungetc(c: c_int, f: FILE);
|
||||
fn feof(f: FILE) -> c_int;
|
||||
@ -93,6 +96,11 @@ fn fclose(file: libc::FILE) {
|
||||
libc::fclose(file)
|
||||
}
|
||||
|
||||
fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
|
||||
// FIXME do something more apropriate
|
||||
ret libc::fsync(fd);
|
||||
}
|
||||
|
||||
#[abi = "cdecl"]
|
||||
native mod rustrt {
|
||||
fn rust_process_wait(handle: c_int) -> c_int;
|
||||
|
Loading…
Reference in New Issue
Block a user