@@ -13,12 +13,14 @@ use ptr::null;
13
13
use libc:: c_void;
14
14
use rt:: uv:: { Request , NativeHandle , Loop , FsCallback , Buf ,
15
15
status_to_maybe_uv_error_with_loop,
16
- vec_to_uv_buf} ; // , vec_from_uv_buf};
16
+ vec_to_uv_buf, vec_from_uv_buf} ;
17
17
use rt:: uv:: uvll;
18
18
use rt:: uv:: uvll:: * ;
19
19
use path:: Path ;
20
20
use cast:: transmute;
21
21
use libc:: { c_int} ;
22
+ use option:: { None , Some , Option } ;
23
+ use vec;
22
24
23
25
pub struct FsRequest ( * uvll:: uv_fs_t ) ;
24
26
impl Request for FsRequest ;
@@ -110,7 +112,15 @@ impl FsRequest {
110
112
fn cleanup_and_delete ( self ) {
111
113
unsafe {
112
114
let data = uvll:: get_data_for_req ( self . native_handle ( ) ) ;
113
- let _data = transmute :: < * c_void , ~RequestData > ( data) ;
115
+ let mut _data = transmute :: < * c_void , ~RequestData > ( data) ;
116
+ // if set we're going to convert the buf param back into
117
+ // a rust vec, as that's the mechanism by which the raw
118
+ // uv_buf_t's .base field gets freed. We immediately discard
119
+ // the result
120
+ if _data. buf . is_some ( ) {
121
+ let buf = _data. buf . take_unwrap ( ) ;
122
+ vec_from_uv_buf ( buf) ;
123
+ }
114
124
uvll:: set_data_for_req ( self . native_handle ( ) , null :: < ( ) > ( ) ) ;
115
125
uvll:: fs_req_cleanup ( self . native_handle ( ) ) ;
116
126
free_req ( self . native_handle ( ) as * c_void )
@@ -146,6 +156,15 @@ impl FileDescriptor {
146
156
} )
147
157
}
148
158
159
+ pub fn unlink ( loop_ : Loop , path : Path , cb : FsCallback ) -> int {
160
+ let req = FsRequest :: new ( Some ( cb) ) ;
161
+ path. to_str ( ) . to_c_str ( ) . with_ref ( |p| unsafe {
162
+ uvll:: fs_unlink ( loop_. native_handle ( ) ,
163
+ req. native_handle ( ) , p, complete_cb) as int
164
+ } )
165
+ }
166
+
167
+ // as per bnoordhuis in #libuv: offset >= 0 uses prwrite instead of write
149
168
pub fn write ( & self , loop_ : Loop , buf : ~[ u8 ] , offset : i64 , cb : FsCallback )
150
169
-> int {
151
170
let mut req = FsRequest :: new ( Some ( cb) ) ;
@@ -161,6 +180,31 @@ impl FileDescriptor {
161
180
}
162
181
}
163
182
183
+ // really contemplated having this just take a read_len param and have
184
+ // the buf live in the scope of this request.. but decided that exposing
185
+ // an unsafe mechanism that takes a buf_ptr and len would be much more
186
+ // flexible, but the caller is now in the position of managing that
187
+ // buf (with all of the sadface that this entails)
188
+ pub fn read ( & self , loop_ : Loop , buf_ptr : Option < * c_void > , len : uint , offset : i64 , cb : FsCallback )
189
+ -> int {
190
+ let mut req = FsRequest :: new ( Some ( cb) ) ;
191
+ req. get_req_data ( ) . raw_fd = Some ( self . native_handle ( ) ) ;
192
+ unsafe {
193
+ let buf_ptr = match buf_ptr {
194
+ Some ( ptr) => ptr,
195
+ None => {
196
+ let buf = vec:: from_elem ( len, 0u8 ) ;
197
+ let buf = vec_to_uv_buf ( buf) ;
198
+ req. get_req_data ( ) . buf = Some ( buf) ;
199
+ buf. base as * c_void
200
+ }
201
+ } ;
202
+ uvll:: fs_read ( loop_. native_handle ( ) , req. native_handle ( ) ,
203
+ self . native_handle ( ) , buf_ptr,
204
+ len, offset, complete_cb) as int
205
+ }
206
+ }
207
+
164
208
pub fn close ( self , loop_ : Loop , cb : FsCallback ) -> int {
165
209
let req = FsRequest :: new ( Some ( cb) ) ;
166
210
unsafe {
@@ -205,90 +249,99 @@ impl NativeHandle<c_int> for FileDescriptor {
205
249
mod test {
206
250
use super :: * ;
207
251
//use rt::test::*;
252
+ use libc:: { STDOUT_FILENO } ;
253
+ use str;
208
254
use unstable:: run_in_bare_thread;
209
255
use path:: Path ;
210
- use rt:: uv:: { Loop } ; //, slice_to_uv_buf};
211
-
212
- // this is equiv to touch, i guess?
213
- fn file_test_touch_impl ( ) {
214
- debug ! ( "hello?" )
215
- do run_in_bare_thread {
216
- debug!( "In bare thread" )
217
- let mut loop_ = Loop :: new ( ) ;
218
- let flags = map_flag ( O_RDWR ) |
219
- map_flag ( O_CREAT ) ;
220
- // 0644
221
- let mode = map_mode ( S_IWUSR ) |
222
- map_mode ( S_IRUSR ) |
223
- map_mode ( S_IRGRP ) |
224
- map_mode ( S_IROTH ) ;
225
- do FileDescriptor :: open ( loop_, Path ( "./foo.txt" ) , flags, mode)
226
- |req, uverr| {
227
- let loop_ = req. get_loop ( ) ;
228
- assert ! ( uverr. is_none( ) ) ;
229
- let fd = FileDescriptor :: from_open_req ( req) ;
230
- do fd. close ( loop_) |_, uverr| {
231
- assert ! ( uverr. is_none( ) ) ;
232
- } ;
233
- } ;
234
- loop_. run ( ) ;
235
- }
236
- }
237
-
238
- #[ test]
239
- fn file_test_touch ( ) {
240
- file_test_touch_impl ( ) ;
241
- }
256
+ use rt:: uv:: { Loop , vec_from_uv_buf} ; //, slice_to_uv_buf};
257
+ use option:: { None } ;
242
258
243
- fn file_test_tee_impl ( ) {
259
+ fn file_test_full_simple_impl ( ) {
244
260
debug ! ( "hello?" )
245
261
do run_in_bare_thread {
246
262
debug!( "In bare thread" )
247
263
let mut loop_ = Loop :: new ( ) ;
248
- let flags = map_flag ( O_RDWR ) |
264
+ let create_flags = map_flag ( O_RDWR ) |
249
265
map_flag ( O_CREAT ) ;
266
+ let read_flags = map_flag ( O_RDONLY ) ;
250
267
// 0644
251
268
let mode = map_mode ( S_IWUSR ) |
252
269
map_mode ( S_IRUSR ) |
253
270
map_mode ( S_IRGRP ) |
254
271
map_mode ( S_IROTH ) ;
255
- do FileDescriptor :: open ( loop_, Path ( "./file_tee_test.txt" ) , flags, mode)
272
+ let path_str = "./file_full_simple.txt" ;
273
+ let write_val = "hello" ;
274
+ do FileDescriptor :: open ( loop_, Path ( path_str) , create_flags, mode)
256
275
|req, uverr| {
257
276
let loop_ = req. get_loop ( ) ;
258
277
assert ! ( uverr. is_none( ) ) ;
259
278
let fd = FileDescriptor :: from_open_req ( req) ;
260
- let msg: ~[ u8 ] = "hello world" . as_bytes ( ) . to_owned ( ) ;
279
+ let msg: ~[ u8 ] = write_val . as_bytes ( ) . to_owned ( ) ;
261
280
let raw_fd = fd. native_handle ( ) ;
262
281
do fd. write ( loop_, msg, -1 ) |_, uverr| {
263
282
let fd = FileDescriptor ( raw_fd) ;
264
- do fd. close ( loop_) |_, _| {
283
+ do fd. close ( loop_) |req, _| {
284
+ let loop_ = req. get_loop ( ) ;
265
285
assert ! ( uverr. is_none( ) ) ;
286
+ do FileDescriptor :: open ( loop_, Path ( path_str) , read_flags, 0 )
287
+ |req, uverr| {
288
+ assert ! ( uverr. is_none( ) ) ;
289
+ let loop_ = req. get_loop ( ) ;
290
+ let len = 1028 ;
291
+ let fd = FileDescriptor :: from_open_req ( req) ;
292
+ let raw_fd = fd. native_handle ( ) ;
293
+ do fd. read ( loop_, None , len, 0 ) |req, uverr| {
294
+ assert ! ( uverr. is_none( ) ) ;
295
+ let loop_ = req. get_loop ( ) ;
296
+ // we know nread >=0 because uverr is none..
297
+ let nread = req. get_result ( ) as uint ;
298
+ // nread == 0 would be EOF
299
+ if nread > 0 {
300
+ let buf = vec_from_uv_buf (
301
+ req. get_req_data ( ) . buf . take_unwrap ( ) )
302
+ . take_unwrap ( ) ;
303
+ let read_str = str:: from_bytes (
304
+ buf. slice ( 0 ,
305
+ nread) ) ;
306
+ assert ! ( read_str == ~"hello");
307
+ do FileDescriptor(raw_fd).close(loop_) |_,uverr| {
308
+ assert!(uverr.is_none());
309
+ do FileDescriptor::unlink(loop_, Path(path_str))
310
+ |_,uverr| {
311
+ assert!(uverr.is_none());
312
+ };
313
+ };
314
+ }
315
+ };
316
+ };
266
317
};
267
318
};
268
319
};
269
320
loop_.run();
321
+ loop_.close();
270
322
}
271
323
}
272
324
273
325
#[test]
274
- fn file_test_tee ( ) {
275
- file_test_tee_impl ( ) ;
326
+ fn file_test_full_simple () {
327
+ file_test_full_simple_impl ();
276
328
}
277
329
278
- fn naive_print ( input : ~str ) {
279
- do run_in_bare_thread {
280
- let mut loop_ = Loop :: new ( ) ;
281
- let stdout = FileDescriptor ( 1 ) ;
282
- let msg = input. as_bytes ( ) . to_owned ( ) ;
283
- do stdout. write ( loop_, msg, -1 ) |_, uverr| {
284
- assert ! ( uverr. is_none( ) ) ;
285
- } ;
286
- loop_. run ( ) ;
287
- }
330
+ fn naive_print(loop_: Loop, input: ~str) {
331
+ let stdout = FileDescriptor(STDOUT_FILENO);
332
+ let msg = input.as_bytes().to_owned();
333
+ do stdout.write(loop_, msg, -1) |_, uverr| {
334
+ assert!(uverr.is_none());
335
+ };
288
336
}
289
337
290
338
#[test]
291
- fn file_test_println ( ) {
292
- naive_print ( ~"oh yeah. \n ") ;
339
+ fn file_test_write_to_stdout() {
340
+ do run_in_bare_thread {
341
+ let mut loop_ = Loop::new();
342
+ naive_print(loop_, ~" zanzibar!\n ") ;
343
+ loop_. run ( ) ;
344
+ loop_. close ( ) ;
345
+ } ;
293
346
}
294
347
}
0 commit comments