diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index ff1b23286b..cbcf76c7c3 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -1,4 +1,6 @@ -//! stdio implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdio.h.html +//! `stdio.h` implementation. +//! +//! See . use alloc::{ borrow::{Borrow, BorrowMut}, @@ -52,6 +54,7 @@ enum Buffer<'a> { Borrowed(&'a mut [u8]), Owned(Vec), } + impl<'a> Deref for Buffer<'a> { type Target = [u8]; @@ -62,6 +65,7 @@ impl<'a> Deref for Buffer<'a> { } } } + impl<'a> DerefMut for Buffer<'a> { fn deref_mut(&mut self) -> &mut Self::Target { match self { @@ -96,6 +100,7 @@ impl Writer for BufWriter { self.buf.clear(); } } + impl Writer for LineWriter { fn purge(&mut self) { self.inner.buf.clear(); @@ -149,6 +154,7 @@ impl Read for FILE { Ok(len) } } + impl BufRead for FILE { fn fill_buf(&mut self) -> io::Result<&[u8]> { if self.read_pos == self.read_size { @@ -171,6 +177,7 @@ impl BufRead for FILE { self.read_pos = (self.read_pos + i).min(self.read_size); } } + impl Write for FILE { fn write(&mut self, buf: &[u8]) -> io::Result { match self.writer.write(buf) { @@ -191,6 +198,7 @@ impl Write for FILE { } } } + impl WriteFmt for FILE { fn write_str(&mut self, s: &str) -> fmt::Result { self.write_all(s.as_bytes()) @@ -198,11 +206,13 @@ impl WriteFmt for FILE { .map_err(|_| fmt::Error) } } + impl WriteByte for FILE { fn write_u8(&mut self, c: u8) -> fmt::Result { self.write_all(&[c]).map(|_| ()).map_err(|_| fmt::Error) } } + impl FILE { pub fn lock(&mut self) -> LockGuard { unsafe { @@ -253,6 +263,7 @@ impl FILE { } pub struct LockGuard<'a>(&'a mut FILE); + impl<'a> Deref for LockGuard<'a> { type Target = FILE; @@ -260,11 +271,13 @@ impl<'a> Deref for LockGuard<'a> { &self.0 } } + impl<'a> DerefMut for LockGuard<'a> { fn deref_mut(&mut self) -> &mut Self::Target { self.0 } } + impl<'a> Drop for LockGuard<'a> { fn drop(&mut self) { unsafe { @@ -273,6 +286,8 @@ impl<'a> Drop for LockGuard<'a> { } } +/// See . +/// /// Clears EOF and ERR indicators on a stream #[unsafe(no_mangle)] pub unsafe extern "C" fn clearerr(stream: *mut FILE) { @@ -280,6 +295,7 @@ pub unsafe extern "C" fn clearerr(stream: *mut FILE) { stream.flags &= !(F_EOF | F_ERR); } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn ctermid(s: *mut c_char) -> *mut c_char { static mut TERMID: [u8; L_ctermid] = *b"/dev/tty\0"; @@ -291,6 +307,9 @@ pub unsafe extern "C" fn ctermid(s: *mut c_char) -> *mut c_char { strncpy(s, &raw mut TERMID as *mut c_char, L_ctermid) } +/// See +/// +/// Marked legacy in SUS Version 2. // #[unsafe(no_mangle)] pub unsafe extern "C" fn cuserid(s: *mut c_char) -> *mut c_char { let mut buf: Vec = vec![0; 256]; @@ -318,6 +337,8 @@ pub unsafe extern "C" fn cuserid(s: *mut c_char) -> *mut c_char { (*pwdbuf).pw_name } +/// See . +/// /// Close a file /// This function does not guarentee that the file buffer will be flushed or that the file /// descriptor will be closed, so if it is important that the file be written to, use `fflush()` @@ -344,6 +365,8 @@ pub unsafe extern "C" fn fclose(stream: *mut FILE) -> c_int { r as c_int } +/// See . +/// /// Open a file from a file descriptor #[unsafe(no_mangle)] pub unsafe extern "C" fn fdopen(fildes: c_int, mode: *const c_char) -> *mut FILE { @@ -352,6 +375,8 @@ pub unsafe extern "C" fn fdopen(fildes: c_int, mode: *const c_char) -> *mut FILE .or_errno_null_mut() } +/// See . +/// /// Check for EOF #[unsafe(no_mangle)] pub unsafe extern "C" fn feof(stream: *mut FILE) -> c_int { @@ -359,6 +384,8 @@ pub unsafe extern "C" fn feof(stream: *mut FILE) -> c_int { stream.flags & F_EOF } +/// See . +/// /// Check for ERR #[unsafe(no_mangle)] pub unsafe extern "C" fn ferror(stream: *mut FILE) -> c_int { @@ -366,6 +393,8 @@ pub unsafe extern "C" fn ferror(stream: *mut FILE) -> c_int { stream.flags & F_ERR } +/// See . +/// /// Flush output to stream, or sync read position /// Ensure the file is unlocked before calling this function, as it will attempt to lock the file /// itself. @@ -391,6 +420,8 @@ pub unsafe extern "C" fn fflush(stream: *mut FILE) -> c_int { 0 } +/// See . +/// /// Get a single char from a stream #[unsafe(no_mangle)] pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int { @@ -402,6 +433,8 @@ pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int { getc_unlocked(&mut *stream) } +/// See . +/// /// Get the position of the stream and store it in pos #[unsafe(no_mangle)] pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut fpos_t) -> c_int { @@ -413,6 +446,8 @@ pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut fpos_t) -> c_int { 0 } +/// See . +/// /// Get a string from the stream #[unsafe(no_mangle)] pub unsafe extern "C" fn fgets( @@ -481,6 +516,8 @@ pub unsafe extern "C" fn fgets( if wrote { original } else { ptr::null_mut() } } +/// See . +/// /// Get the underlying file descriptor #[unsafe(no_mangle)] pub unsafe extern "C" fn fileno(stream: *mut FILE) -> c_int { @@ -488,6 +525,8 @@ pub unsafe extern "C" fn fileno(stream: *mut FILE) -> c_int { *stream.file } +/// See . +/// /// Lock the file /// Do not call any functions other than those with the `_unlocked` postfix while the file is /// locked @@ -496,6 +535,8 @@ pub unsafe extern "C" fn flockfile(file: *mut FILE) { (*file).lock.manual_lock(); } +/// See . +/// /// Open the file in mode `mode` #[unsafe(no_mangle)] pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE { @@ -535,6 +576,10 @@ pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> .or_errno_null_mut() } +/// See . +/// +/// Non-POSIX. From Solaris. +/// /// Clear the buffers of a stream /// Ensure the file is unlocked before calling this function, as it will attempt to lock the file /// itself. @@ -546,6 +591,8 @@ pub unsafe extern "C" fn __fpurge(stream: *mut FILE) { } } +/// See . +/// /// Insert a character into the stream #[unsafe(no_mangle)] pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int { @@ -557,6 +604,8 @@ pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int { putc_unlocked(c, &mut *stream) } +/// See . +/// /// Insert a string into a stream #[unsafe(no_mangle)] pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int { @@ -574,6 +623,8 @@ pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int { } } +/// See . +/// /// Read `nitems` of size `size` into `ptr` from `stream` #[unsafe(no_mangle)] pub unsafe extern "C" fn fread( @@ -602,6 +653,7 @@ pub unsafe extern "C" fn fread( (read / size as usize) as size_t } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn freopen( filename: *const c_char, @@ -657,12 +709,16 @@ pub unsafe extern "C" fn freopen( stream } +/// See . +/// /// Seek to an offset `offset` from `whence` #[unsafe(no_mangle)] pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int { fseeko(stream, offset as off_t, whence) } +/// See . +/// /// Seek to an offset `offset` from `whence` #[unsafe(no_mangle)] pub unsafe extern "C" fn fseeko(stream: *mut FILE, off: off_t, whence: c_int) -> c_int { @@ -694,24 +750,31 @@ pub unsafe fn fseek_locked(stream: &mut FILE, mut off: off_t, whence: c_int) -> 0 } +/// See . +/// /// Seek to a position `pos` in the file from the beginning of the file #[unsafe(no_mangle)] pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const fpos_t) -> c_int { fseeko(stream, *pos, SEEK_SET) } +/// See . +/// /// Get the current position of the cursor in the file #[unsafe(no_mangle)] pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long { ftello(stream) as c_long } +/// See . +/// /// Get the current position of the cursor in the file #[unsafe(no_mangle)] pub unsafe extern "C" fn ftello(stream: *mut FILE) -> off_t { let mut stream = (*stream).lock(); ftell_locked(&mut *stream) } + pub unsafe extern "C" fn ftell_locked(stream: &mut FILE) -> off_t { let pos = Sys::lseek(*stream.file, 0, SEEK_CUR).or_minus_one_errno(); if pos < 0 { @@ -721,6 +784,8 @@ pub unsafe extern "C" fn ftell_locked(stream: &mut FILE) -> off_t { pos - (stream.read_size - stream.read_pos) as off_t - stream.unget.len() as off_t } +/// See . +/// /// Try to lock the file. Returns 0 for success, 1 for failure #[unsafe(no_mangle)] pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> c_int { @@ -731,12 +796,16 @@ pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> c_int { } } +/// See . +/// /// Unlock the file #[unsafe(no_mangle)] pub unsafe extern "C" fn funlockfile(file: *mut FILE) { (*file).lock.manual_unlock(); } +/// See . +/// /// Write `nitems` of size `size` from `ptr` to `stream` #[unsafe(no_mangle)] pub unsafe extern "C" fn fwrite( @@ -764,6 +833,8 @@ pub unsafe extern "C" fn fwrite( (written / size as usize) as size_t } +/// See . +/// /// Get a single char from a stream #[unsafe(no_mangle)] pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { @@ -771,12 +842,16 @@ pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { getc_unlocked(&mut *stream) } +/// See . +/// /// Get a single char from `stdin` #[unsafe(no_mangle)] pub unsafe extern "C" fn getchar() -> c_int { fgetc(&mut *stdin) } +/// See . +/// /// Get a char from a stream without locking the stream #[unsafe(no_mangle)] pub unsafe extern "C" fn getc_unlocked(stream: *mut FILE) -> c_int { @@ -792,18 +867,29 @@ pub unsafe extern "C" fn getc_unlocked(stream: *mut FILE) -> c_int { } } +/// See . +/// /// Get a char from `stdin` without locking `stdin` #[unsafe(no_mangle)] pub unsafe extern "C" fn getchar_unlocked() -> c_int { getc_unlocked(&mut *stdin) } +/// See . +/// +/// Marked obsolescent in issue 7. +/// `fgets` is recommended instead, which is what this implementation calls. +/// /// Get a string from `stdin` #[unsafe(no_mangle)] pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char { fgets(s, c_int::max_value(), &mut *stdin) } +/// See . +/// +/// Was marked legacy and removed in issue 6. +/// /// Get an integer from `stream` #[unsafe(no_mangle)] pub unsafe extern "C" fn getw(stream: *mut FILE) -> c_int { @@ -821,6 +907,7 @@ pub unsafe extern "C" fn getw(stream: *mut FILE) -> c_int { } } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn pclose(stream: *mut FILE) -> c_int { // TODO: rusty error handling? @@ -845,6 +932,7 @@ pub unsafe extern "C" fn pclose(stream: *mut FILE) -> c_int { wstatus } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn perror(s: *const c_char) { let err = ERRNO.get(); @@ -864,6 +952,7 @@ pub unsafe extern "C" fn perror(s: *const c_char) { } } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn popen(command: *const c_char, mode: *const c_char) -> *mut FILE { //TODO: share code with system @@ -958,6 +1047,8 @@ pub unsafe extern "C" fn popen(command: *const c_char, mode: *const c_char) -> * } } +/// See . +/// /// Put a character `c` into `stream` #[unsafe(no_mangle)] pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { @@ -965,12 +1056,16 @@ pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { putc_unlocked(c, &mut *stream) } +/// See . +/// /// Put a character `c` into `stdout` #[unsafe(no_mangle)] pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, &mut *stdout) } +/// See . +/// /// Put a character `c` into `stream` without locking `stream` #[unsafe(no_mangle)] pub unsafe extern "C" fn putc_unlocked(c: c_int, stream: *mut FILE) -> c_int { @@ -984,12 +1079,16 @@ pub unsafe extern "C" fn putc_unlocked(c: c_int, stream: *mut FILE) -> c_int { } } +/// See . +/// /// Put a character `c` into `stdout` without locking `stdout` #[unsafe(no_mangle)] pub unsafe extern "C" fn putchar_unlocked(c: c_int) -> c_int { putc_unlocked(c, stdout) } +/// See . +/// /// Put a string `s` into `stdout` #[unsafe(no_mangle)] pub unsafe extern "C" fn puts(s: *const c_char) -> c_int { @@ -1009,12 +1108,18 @@ pub unsafe extern "C" fn puts(s: *const c_char) -> c_int { 0 } +/// See . +/// +/// Marked legacy in SUS Version 2. +/// /// Put an integer `w` into `stream` #[unsafe(no_mangle)] pub unsafe extern "C" fn putw(w: c_int, stream: *mut FILE) -> c_int { fwrite(&w as *const c_int as _, mem::size_of_val(&w), 1, stream) as i32 - 1 } +/// See . +/// /// Delete file or directory `path` #[unsafe(no_mangle)] pub unsafe extern "C" fn remove(path: *const c_char) -> c_int { @@ -1025,6 +1130,7 @@ pub unsafe extern "C" fn remove(path: *const c_char) -> c_int { .or_minus_one_errno() } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn rename(oldpath: *const c_char, newpath: *const c_char) -> c_int { let oldpath = CStr::from_ptr(oldpath); @@ -1034,6 +1140,7 @@ pub unsafe extern "C" fn rename(oldpath: *const c_char, newpath: *const c_char) .or_minus_one_errno() } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn renameat( old_dir: c_int, @@ -1048,6 +1155,9 @@ pub unsafe extern "C" fn renameat( .or_minus_one_errno() } +/// See . +/// +/// Non-POSIX. Seems to be a GNU extension. #[unsafe(no_mangle)] pub unsafe extern "C" fn renameat2( old_dir: c_int, @@ -1063,12 +1173,16 @@ pub unsafe extern "C" fn renameat2( .or_minus_one_errno() } +/// See . +/// /// Rewind `stream` back to the beginning of it #[unsafe(no_mangle)] pub unsafe extern "C" fn rewind(stream: *mut FILE) { fseeko(stream, 0, SEEK_SET); } +/// See . +/// /// Reset `stream` to use buffer `buf`. Buffer must be `BUFSIZ` in length #[unsafe(no_mangle)] pub unsafe extern "C" fn setbuf(stream: *mut FILE, buf: *mut c_char) { @@ -1080,12 +1194,18 @@ pub unsafe extern "C" fn setbuf(stream: *mut FILE, buf: *mut c_char) { ); } +/// See . +/// +/// Non-POSIX. +/// /// Set buffering of `stream` to line buffered #[unsafe(no_mangle)] pub unsafe extern "C" fn setlinebuf(stream: *mut FILE) { setvbuf(stream, ptr::null_mut(), _IOLBF, 0); } +/// See . +/// /// Reset `stream` to use buffer `buf` of size `size` /// If this isn't the meaning of unsafe, idk what is #[unsafe(no_mangle)] @@ -1113,6 +1233,9 @@ pub unsafe extern "C" fn setvbuf( 0 } +/// See . +/// +/// Marked obsolescent in issue 7. #[unsafe(no_mangle)] pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char { unsafe fn is_appropriate(pos_dir: *const c_char) -> bool { @@ -1156,6 +1279,7 @@ pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut out_buf } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn tmpfile() -> *mut FILE { let mut file_name = *b"/tmp/tmpfileXXXXXX\0"; @@ -1179,6 +1303,9 @@ pub unsafe extern "C" fn tmpfile() -> *mut FILE { fp } +/// See . +/// +/// Marked obsolescent in issue 7. #[unsafe(no_mangle)] pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char { let buf = if s.is_null() { @@ -1204,6 +1331,8 @@ unsafe extern "C" fn tmpnam_inner(buf: *mut c_char, offset: usize) -> *mut c_cha if *buf == 0 { ptr::null_mut() } else { buf } } +/// See . +/// /// Push character `c` back onto `stream` so it'll be read next #[unsafe(no_mangle)] pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int { @@ -1216,6 +1345,7 @@ pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int { c } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vfprintf(file: *mut FILE, format: *const c_char, ap: va_list) -> c_int { let mut file = (*file).lock(); @@ -1225,6 +1355,8 @@ pub unsafe extern "C" fn vfprintf(file: *mut FILE, format: *const c_char, ap: va printf::printf(&mut *file, CStr::from_ptr(format), ap) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn fprintf( file: *mut FILE, @@ -1234,6 +1366,7 @@ pub unsafe extern "C" fn fprintf( vfprintf(file, format, __valist.as_va_list()) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vdprintf(fd: c_int, format: *const c_char, ap: va_list) -> c_int { let mut f = File::new(fd); @@ -1244,20 +1377,26 @@ pub unsafe extern "C" fn vdprintf(fd: c_int, format: *const c_char, ap: va_list) printf::printf(f, CStr::from_ptr(format), ap) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn dprintf(fd: c_int, format: *const c_char, mut __valist: ...) -> c_int { vdprintf(fd, format, __valist.as_va_list()) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vprintf(format: *const c_char, ap: va_list) -> c_int { vfprintf(&mut *stdout, format, ap) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn printf(format: *const c_char, mut __valist: ...) -> c_int { vfprintf(&mut *stdout, format, __valist.as_va_list()) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vasprintf( strp: *mut *mut c_char, @@ -1271,6 +1410,8 @@ pub unsafe extern "C" fn vasprintf( *strp = alloc_writer.leak() as *mut c_char; ret } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn asprintf( strp: *mut *mut c_char, @@ -1280,6 +1421,7 @@ pub unsafe extern "C" fn asprintf( vasprintf(strp, format, __valist.as_va_list()) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vsnprintf( s: *mut c_char, @@ -1293,6 +1435,8 @@ pub unsafe extern "C" fn vsnprintf( ap, ) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn snprintf( s: *mut c_char, @@ -1307,6 +1451,7 @@ pub unsafe extern "C" fn snprintf( ) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vsprintf(s: *mut c_char, format: *const c_char, ap: va_list) -> c_int { printf::printf( @@ -1315,6 +1460,8 @@ pub unsafe extern "C" fn vsprintf(s: *mut c_char, format: *const c_char, ap: va_ ap, ) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn sprintf( s: *mut c_char, @@ -1328,6 +1475,7 @@ pub unsafe extern "C" fn sprintf( ) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vfscanf(file: *mut FILE, format: *const c_char, ap: va_list) -> c_int { let ret = { @@ -1342,6 +1490,8 @@ pub unsafe extern "C" fn vfscanf(file: *mut FILE, format: *const c_char, ap: va_ }; ret } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn fscanf( file: *mut FILE, @@ -1351,20 +1501,26 @@ pub unsafe extern "C" fn fscanf( vfscanf(file, format, __valist.as_va_list()) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vscanf(format: *const c_char, ap: va_list) -> c_int { vfscanf(&mut *stdin, format, ap) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn scanf(format: *const c_char, mut __valist: ...) -> c_int { vfscanf(&mut *stdin, format, __valist.as_va_list()) } +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vsscanf(s: *const c_char, format: *const c_char, ap: va_list) -> c_int { let reader = (s as *const u8).into(); scanf::scanf(reader, format, ap) } + +/// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn sscanf( s: *const c_char,