1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Blocking posix-based file I/O
12
13 use libc::{c_int, c_void};
14 use libc;
15 use std::c_str::CString;
16 use std::io::IoError;
17 use std::io;
18 use std::mem;
19 use std::rt::rtio;
20 use std::sync::arc::UnsafeArc;
21
22 use io::{IoResult, retry, keep_going};
23
24 pub type fd_t = libc::c_int;
25
26 struct Inner {
27 fd: fd_t,
28 close_on_drop: bool,
29 }
30
31 pub struct FileDesc {
32 inner: UnsafeArc<Inner>
33 }
34
35 impl FileDesc {
36 /// Create a `FileDesc` from an open C file descriptor.
37 ///
38 /// The `FileDesc` will take ownership of the specified file descriptor and
39 /// close it upon destruction if the `close_on_drop` flag is true, otherwise
40 /// it will not close the file descriptor when this `FileDesc` is dropped.
41 ///
42 /// Note that all I/O operations done on this object will be *blocking*, but
43 /// they do not require the runtime to be active.
44 pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
45 FileDesc { inner: UnsafeArc::new(Inner {
46 fd: fd,
47 close_on_drop: close_on_drop
48 }) }
49 }
50
51 // FIXME(#10465) these functions should not be public, but anything in
52 // native::io wanting to use them is forced to have all the
53 // rtio traits in scope
54 pub fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
55 let ret = retry(|| unsafe {
56 libc::read(self.fd(),
57 buf.as_mut_ptr() as *mut libc::c_void,
58 buf.len() as libc::size_t) as libc::c_int
59 });
60 if ret == 0 {
61 Err(io::standard_error(io::EndOfFile))
62 } else if ret < 0 {
63 Err(super::last_error())
64 } else {
65 Ok(ret as uint)
66 }
67 }
68 pub fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
69 let ret = keep_going(buf, |buf, len| {
70 unsafe {
71 libc::write(self.fd(), buf as *libc::c_void,
72 len as libc::size_t) as i64
73 }
74 });
75 if ret < 0 {
76 Err(super::last_error())
77 } else {
78 Ok(())
79 }
80 }
81
82 pub fn fd(&self) -> fd_t {
83 // This unsafety is fine because we're just reading off the file
84 // descriptor, no one is modifying this.
85 unsafe { (*self.inner.get()).fd }
86 }
87 }
88
89 impl io::Reader for FileDesc {
90 fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
91 self.inner_read(buf)
92 }
93 }
94
95 impl io::Writer for FileDesc {
96 fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
97 self.inner_write(buf)
98 }
99 }
100
101 impl rtio::RtioFileStream for FileDesc {
102 fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
103 self.inner_read(buf).map(|i| i as int)
104 }
105 fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
106 self.inner_write(buf)
107 }
108 fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
109 match retry(|| unsafe {
110 libc::pread(self.fd(), buf.as_ptr() as *libc::c_void,
111 buf.len() as libc::size_t,
112 offset as libc::off_t) as libc::c_int
113 }) {
114 -1 => Err(super::last_error()),
115 n => Ok(n as int)
116 }
117 }
118 fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
119 super::mkerr_libc(retry(|| unsafe {
120 libc::pwrite(self.fd(), buf.as_ptr() as *libc::c_void,
121 buf.len() as libc::size_t, offset as libc::off_t)
122 } as c_int))
123 }
124 fn seek(&mut self, pos: i64, whence: io::SeekStyle) -> Result<u64, IoError> {
125 let whence = match whence {
126 io::SeekSet => libc::SEEK_SET,
127 io::SeekEnd => libc::SEEK_END,
128 io::SeekCur => libc::SEEK_CUR,
129 };
130 let n = unsafe { libc::lseek(self.fd(), pos as libc::off_t, whence) };
131 if n < 0 {
132 Err(super::last_error())
133 } else {
134 Ok(n as u64)
135 }
136 }
137 fn tell(&self) -> Result<u64, IoError> {
138 let n = unsafe { libc::lseek(self.fd(), 0, libc::SEEK_CUR) };
139 if n < 0 {
140 Err(super::last_error())
141 } else {
142 Ok(n as u64)
143 }
144 }
145 fn fsync(&mut self) -> Result<(), IoError> {
146 super::mkerr_libc(retry(|| unsafe { libc::fsync(self.fd()) }))
147 }
148 fn datasync(&mut self) -> Result<(), IoError> {
149 return super::mkerr_libc(os_datasync(self.fd()));
150
151 #[cfg(target_os = "macos")]
152 fn os_datasync(fd: c_int) -> c_int {
153 unsafe { libc::fcntl(fd, libc::F_FULLFSYNC) }
154 }
155 #[cfg(target_os = "linux")]
156 fn os_datasync(fd: c_int) -> c_int {
157 retry(|| unsafe { libc::fdatasync(fd) })
158 }
159 #[cfg(not(target_os = "macos"), not(target_os = "linux"))]
160 fn os_datasync(fd: c_int) -> c_int {
161 retry(|| unsafe { libc::fsync(fd) })
162 }
163 }
164 fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
165 super::mkerr_libc(retry(|| unsafe {
166 libc::ftruncate(self.fd(), offset as libc::off_t)
167 }))
168 }
169 }
170
171 impl rtio::RtioPipe for FileDesc {
172 fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
173 self.inner_read(buf)
174 }
175 fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
176 self.inner_write(buf)
177 }
178 fn clone(&self) -> Box<rtio::RtioPipe:Send> {
179 box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
180 }
181
182 // Only supported on named pipes currently. Note that this doesn't have an
183 // impact on the std::io primitives, this is never called via
184 // std::io::PipeStream. If the functionality is exposed in the future, then
185 // these methods will need to be implemented.
186 fn close_read(&mut self) -> Result<(), IoError> {
187 Err(io::standard_error(io::InvalidInput))
188 }
189 fn close_write(&mut self) -> Result<(), IoError> {
190 Err(io::standard_error(io::InvalidInput))
191 }
192 fn set_timeout(&mut self, _t: Option<u64>) {}
193 fn set_read_timeout(&mut self, _t: Option<u64>) {}
194 fn set_write_timeout(&mut self, _t: Option<u64>) {}
195 }
196
197 impl rtio::RtioTTY for FileDesc {
198 fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
199 self.inner_read(buf)
200 }
201 fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
202 self.inner_write(buf)
203 }
204 fn set_raw(&mut self, _raw: bool) -> Result<(), IoError> {
205 Err(super::unimpl())
206 }
207 fn get_winsize(&mut self) -> Result<(int, int), IoError> {
208 Err(super::unimpl())
209 }
210 fn isatty(&self) -> bool { false }
211 }
212
213 impl Drop for Inner {
214 fn drop(&mut self) {
215 // closing stdio file handles makes no sense, so never do it. Also, note
216 // that errors are ignored when closing a file descriptor. The reason
217 // for this is that if an error occurs we don't actually know if the
218 // file descriptor was closed or not, and if we retried (for something
219 // like EINTR), we might close another valid file descriptor (opened
220 // after we closed ours.
221 if self.close_on_drop && self.fd > libc::STDERR_FILENO {
222 let n = unsafe { libc::close(self.fd) };
223 if n != 0 {
224 println!("error {} when closing file descriptor {}", n,
225 self.fd);
226 }
227 }
228 }
229 }
230
231 pub struct CFile {
232 file: *libc::FILE,
233 fd: FileDesc,
234 }
235
236 impl CFile {
237 /// Create a `CFile` from an open `FILE` pointer.
238 ///
239 /// The `CFile` takes ownership of the `FILE` pointer and will close it upon
240 /// destruction.
241 pub fn new(file: *libc::FILE) -> CFile {
242 CFile {
243 file: file,
244 fd: FileDesc::new(unsafe { libc::fileno(file) }, false)
245 }
246 }
247
248 pub fn flush(&mut self) -> Result<(), IoError> {
249 super::mkerr_libc(retry(|| unsafe { libc::fflush(self.file) }))
250 }
251 }
252
253 impl rtio::RtioFileStream for CFile {
254 fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
255 let ret = keep_going(buf, |buf, len| {
256 unsafe {
257 libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
258 self.file) as i64
259 }
260 });
261 if ret == 0 {
262 Err(io::standard_error(io::EndOfFile))
263 } else if ret < 0 {
264 Err(super::last_error())
265 } else {
266 Ok(ret as int)
267 }
268 }
269
270 fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
271 let ret = keep_going(buf, |buf, len| {
272 unsafe {
273 libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
274 self.file) as i64
275 }
276 });
277 if ret < 0 {
278 Err(super::last_error())
279 } else {
280 Ok(())
281 }
282 }
283
284 fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
285 self.flush().and_then(|()| self.fd.pread(buf, offset))
286 }
287 fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
288 self.flush().and_then(|()| self.fd.pwrite(buf, offset))
289 }
290 fn seek(&mut self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
291 let whence = match style {
292 io::SeekSet => libc::SEEK_SET,
293 io::SeekEnd => libc::SEEK_END,
294 io::SeekCur => libc::SEEK_CUR,
295 };
296 let n = unsafe { libc::fseek(self.file, pos as libc::c_long, whence) };
297 if n < 0 {
298 Err(super::last_error())
299 } else {
300 Ok(n as u64)
301 }
302 }
303 fn tell(&self) -> Result<u64, IoError> {
304 let ret = unsafe { libc::ftell(self.file) };
305 if ret < 0 {
306 Err(super::last_error())
307 } else {
308 Ok(ret as u64)
309 }
310 }
311 fn fsync(&mut self) -> Result<(), IoError> {
312 self.flush().and_then(|()| self.fd.fsync())
313 }
314 fn datasync(&mut self) -> Result<(), IoError> {
315 self.flush().and_then(|()| self.fd.fsync())
316 }
317 fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
318 self.flush().and_then(|()| self.fd.truncate(offset))
319 }
320 }
321
322 impl Drop for CFile {
323 fn drop(&mut self) {
324 unsafe { let _ = libc::fclose(self.file); }
325 }
326 }
327
328 pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
329 -> IoResult<FileDesc> {
330 let flags = match fm {
331 io::Open => 0,
332 io::Append => libc::O_APPEND,
333 io::Truncate => libc::O_TRUNC,
334 };
335 // Opening with a write permission must silently create the file.
336 let (flags, mode) = match fa {
337 io::Read => (flags | libc::O_RDONLY, 0),
338 io::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
339 libc::S_IRUSR | libc::S_IWUSR),
340 io::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
341 libc::S_IRUSR | libc::S_IWUSR),
342 };
343
344 match retry(|| unsafe { libc::open(path.with_ref(|p| p), flags, mode) }) {
345 -1 => Err(super::last_error()),
346 fd => Ok(FileDesc::new(fd, true)),
347 }
348 }
349
350 pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
351 super::mkerr_libc(retry(|| unsafe {
352 libc::mkdir(p.with_ref(|p| p), mode.bits() as libc::mode_t)
353 }))
354 }
355
356 pub fn readdir(p: &CString) -> IoResult<Vec<Path>> {
357 use libc::{dirent_t};
358 use libc::{opendir, readdir_r, closedir};
359
360 fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
361 let root = unsafe { CString::new(root.with_ref(|p| p), false) };
362 let root = Path::new(root);
363
364 dirs.move_iter().filter(|path| {
365 path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..")
366 }).map(|path| root.join(path)).collect()
367 }
368
369 extern {
370 fn rust_dirent_t_size() -> libc::c_int;
371 fn rust_list_dir_val(ptr: *mut dirent_t) -> *libc::c_char;
372 }
373
374 let size = unsafe { rust_dirent_t_size() };
375 let mut buf = Vec::<u8>::with_capacity(size as uint);
376 let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;
377
378 let dir_ptr = p.with_ref(|buf| unsafe { opendir(buf) });
379
380 if dir_ptr as uint != 0 {
381 let mut paths = vec!();
382 let mut entry_ptr = 0 as *mut dirent_t;
383 while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
384 if entry_ptr.is_null() { break }
385 let cstr = unsafe {
386 CString::new(rust_list_dir_val(entry_ptr), false)
387 };
388 paths.push(Path::new(cstr));
389 }
390 assert_eq!(unsafe { closedir(dir_ptr) }, 0);
391 Ok(prune(p, paths))
392 } else {
393 Err(super::last_error())
394 }
395 }
396
397 pub fn unlink(p: &CString) -> IoResult<()> {
398 super::mkerr_libc(retry(|| unsafe { libc::unlink(p.with_ref(|p| p)) }))
399 }
400
401 pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
402 super::mkerr_libc(retry(|| unsafe {
403 libc::rename(old.with_ref(|p| p), new.with_ref(|p| p))
404 }))
405 }
406
407 pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
408 super::mkerr_libc(retry(|| unsafe {
409 libc::chmod(p.with_ref(|p| p), mode.bits() as libc::mode_t)
410 }))
411 }
412
413 pub fn rmdir(p: &CString) -> IoResult<()> {
414 super::mkerr_libc(retry(|| unsafe {
415 libc::rmdir(p.with_ref(|p| p))
416 }))
417 }
418
419 pub fn chown(p: &CString, uid: int, gid: int) -> IoResult<()> {
420 super::mkerr_libc(retry(|| unsafe {
421 libc::chown(p.with_ref(|p| p), uid as libc::uid_t,
422 gid as libc::gid_t)
423 }))
424 }
425
426 pub fn readlink(p: &CString) -> IoResult<Path> {
427 let p = p.with_ref(|p| p);
428 let mut len = unsafe { libc::pathconf(p, libc::_PC_NAME_MAX) };
429 if len == -1 {
430 len = 1024; // FIXME: read PATH_MAX from C ffi?
431 }
432 let mut buf: Vec<u8> = Vec::with_capacity(len as uint);
433 match retry(|| unsafe {
434 libc::readlink(p, buf.as_ptr() as *mut libc::c_char,
435 len as libc::size_t) as libc::c_int
436 }) {
437 -1 => Err(super::last_error()),
438 n => {
439 assert!(n > 0);
440 unsafe { buf.set_len(n as uint); }
441 Ok(Path::new(buf))
442 }
443 }
444 }
445
446 pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
447 super::mkerr_libc(retry(|| unsafe {
448 libc::symlink(src.with_ref(|p| p), dst.with_ref(|p| p))
449 }))
450 }
451
452 pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
453 super::mkerr_libc(retry(|| unsafe {
454 libc::link(src.with_ref(|p| p), dst.with_ref(|p| p))
455 }))
456 }
457
458 fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
459 let path = unsafe { CString::new(path.with_ref(|p| p), false) };
460
461 // FileStat times are in milliseconds
462 fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
463
464 let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
465 libc::S_IFREG => io::TypeFile,
466 libc::S_IFDIR => io::TypeDirectory,
467 libc::S_IFIFO => io::TypeNamedPipe,
468 libc::S_IFBLK => io::TypeBlockSpecial,
469 libc::S_IFLNK => io::TypeSymlink,
470 _ => io::TypeUnknown,
471 };
472
473 #[cfg(not(target_os = "linux"), not(target_os = "android"))]
474 fn flags(stat: &libc::stat) -> u64 { stat.st_flags as u64 }
475 #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
476 fn flags(_stat: &libc::stat) -> u64 { 0 }
477
478 #[cfg(not(target_os = "linux"), not(target_os = "android"))]
479 fn gen(stat: &libc::stat) -> u64 { stat.st_gen as u64 }
480 #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
481 fn gen(_stat: &libc::stat) -> u64 { 0 }
482
483 io::FileStat {
484 path: Path::new(path),
485 size: stat.st_size as u64,
486 kind: kind,
487 perm: unsafe {
488 io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
489 },
490 created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
491 modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
492 accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
493 unstable: io::UnstableFileStat {
494 device: stat.st_dev as u64,
495 inode: stat.st_ino as u64,
496 rdev: stat.st_rdev as u64,
497 nlink: stat.st_nlink as u64,
498 uid: stat.st_uid as u64,
499 gid: stat.st_gid as u64,
500 blksize: stat.st_blksize as u64,
501 blocks: stat.st_blocks as u64,
502 flags: flags(stat),
503 gen: gen(stat),
504 }
505 }
506 }
507
508 pub fn stat(p: &CString) -> IoResult<io::FileStat> {
509 let mut stat: libc::stat = unsafe { mem::uninit() };
510 match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) {
511 0 => Ok(mkstat(&stat, p)),
512 _ => Err(super::last_error()),
513 }
514 }
515
516 pub fn lstat(p: &CString) -> IoResult<io::FileStat> {
517 let mut stat: libc::stat = unsafe { mem::uninit() };
518 match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
519 0 => Ok(mkstat(&stat, p)),
520 _ => Err(super::last_error()),
521 }
522 }
523
524 pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
525 let buf = libc::utimbuf {
526 actime: (atime / 1000) as libc::time_t,
527 modtime: (mtime / 1000) as libc::time_t,
528 };
529 super::mkerr_libc(retry(|| unsafe {
530 libc::utime(p.with_ref(|p| p), &buf)
531 }))
532 }
533
534 #[cfg(test)]
535 mod tests {
536 use super::{CFile, FileDesc};
537 use std::io;
538 use libc;
539 use std::os;
540 use std::rt::rtio::RtioFileStream;
541
542 #[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer
543 #[test]
544 fn test_file_desc() {
545 // Run this test with some pipes so we don't have to mess around with
546 // opening or closing files.
547 let os::Pipe { input, out } = os::pipe();
548 let mut reader = FileDesc::new(input, true);
549 let mut writer = FileDesc::new(out, true);
550
551 writer.inner_write(bytes!("test")).unwrap();
552 let mut buf = [0u8, ..4];
553 match reader.inner_read(buf) {
554 Ok(4) => {
555 assert_eq!(buf[0], 't' as u8);
556 assert_eq!(buf[1], 'e' as u8);
557 assert_eq!(buf[2], 's' as u8);
558 assert_eq!(buf[3], 't' as u8);
559 }
560 r => fail!("invalid read: {:?}", r)
561 }
562
563 assert!(writer.inner_read(buf).is_err());
564 assert!(reader.inner_write(buf).is_err());
565 }
566
567 #[test]
568 fn test_cfile() {
569 unsafe {
570 let f = libc::tmpfile();
571 assert!(!f.is_null());
572 let mut file = CFile::new(f);
573
574 file.write(bytes!("test")).unwrap();
575 let mut buf = [0u8, ..4];
576 let _ = file.seek(0, io::SeekSet).unwrap();
577 match file.read(buf) {
578 Ok(4) => {
579 assert_eq!(buf[0], 't' as u8);
580 assert_eq!(buf[1], 'e' as u8);
581 assert_eq!(buf[2], 's' as u8);
582 assert_eq!(buf[3], 't' as u8);
583 }
584 r => fail!("invalid read: {:?}", r)
585 }
586 }
587 }
588 }
libnative/io/file_unix.rs:462:4-462:4 -fn- definition:
fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
libc::S_IFREG => io::TypeFile,
references:- 3490: created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
491: modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
492: accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
493: unstable: io::UnstableFileStat {
libnative/io/file_unix.rs:30:1-30:1 -struct- definition:
pub struct FileDesc {
inner: UnsafeArc<Inner>
}
references:- 1444: pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
45: FileDesc { inner: UnsafeArc::new(Inner {
46: fd: fd,
--
178: fn clone(&self) -> Box<rtio::RtioPipe:Send> {
179: box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
180: }
--
232: file: *libc::FILE,
233: fd: FileDesc,
234: }
--
328: pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
329: -> IoResult<FileDesc> {
330: let flags = match fm {
libnative/io/process.rs:
69: pub fn spawn(config: p::ProcessConfig)
70: -> Result<(Process, Vec<Option<file::FileDesc>>), io::IoError>
71: {
--
551: fn fail(output: &mut file::FileDesc) -> ! {
552: let errno = os::errno();
libnative/io/file_unix.rs:
101: impl rtio::RtioFileStream for FileDesc {
102: fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
libnative/io/file_unix.rs:25:1-25:1 -struct- definition:
struct Inner {
fd: fd_t,
close_on_drop: bool,
references:- 3213: impl Drop for Inner {
214: fn drop(&mut self) {
libnative/io/file_unix.rs:230:1-230:1 -struct- definition:
pub struct CFile {
file: *libc::FILE,
fd: FileDesc,
references:- 5241: pub fn new(file: *libc::FILE) -> CFile {
242: CFile {
243: file: file,
--
322: impl Drop for CFile {
323: fn drop(&mut self) {
libnative/io/file_unix.rs:457:1-457:1 -fn- definition:
fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
let path = unsafe { CString::new(path.with_ref(|p| p), false) };
// FileStat times are in milliseconds
references:- 2518: match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
519: 0 => Ok(mkstat(&stat, p)),
520: _ => Err(super::last_error()),
libnative/io/file_unix.rs:23:1-23:1 -NK_AS_STR_TODO- definition:
pub type fd_t = libc::c_int;
struct Inner {
fd: fd_t,
references:- 1082: pub fn fd(&self) -> fd_t {
83: // This unsafety is fine because we're just reading off the file
libnative/io/pipe_unix.rs:
27: fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {
28: match unsafe { libc::socket(libc::AF_UNIX, ty, 0) } {
--
64: impl Inner {
65: fn new(fd: fd_t) -> Inner {
66: Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
--
241: impl UnixAcceptor {
242: fn fd(&self) -> fd_t { self.listener.fd() }
libnative/io/net.rs:
libnative/io/pipe_unix.rs:
59: struct Inner {
60: fd: fd_t,
61: lock: mutex::NativeMutex,