Rewrite IO to use core-io library
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
#ifndef _BITS_STDIO_H
|
||||
#define _BITS_STDIO_H
|
||||
|
||||
#define EOF (-1)
|
||||
#define BUFSIZ 1024
|
||||
|
||||
typedef struct FILE FILE;
|
||||
|
||||
int fprintf(FILE * stream, const char * fmt, ...);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use c_str::CStr;
|
||||
use core::ops::Deref;
|
||||
use header::fcntl::O_CREAT;
|
||||
use header::unistd::{SEEK_SET, SEEK_CUR, SEEK_END};
|
||||
use io;
|
||||
@@ -11,48 +12,70 @@ fn last_os_error() -> io::Error {
|
||||
io::Error::from_raw_os_error(errno)
|
||||
}
|
||||
|
||||
pub struct File(c_int);
|
||||
pub struct File {
|
||||
pub fd: c_int,
|
||||
/// To avoid self referential FILE struct that needs both a reader and a writer,
|
||||
/// make "reference" files that share fd but don't close on drop.
|
||||
pub reference: bool
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn new(fd: c_int) -> Self {
|
||||
Self {
|
||||
fd,
|
||||
reference: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(path: &CStr, oflag: c_int) -> io::Result<Self> {
|
||||
match Sys::open(path, oflag, 0) {
|
||||
-1 => Err(last_os_error()),
|
||||
ok => Ok(File(ok)),
|
||||
ok => Ok(Self::new(ok)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(path: &CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
|
||||
match Sys::open(path, oflag | O_CREAT, mode) {
|
||||
-1 => Err(last_os_error()),
|
||||
ok => Ok(File(ok)),
|
||||
ok => Ok(Self::new(ok)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sync_all(&self) -> io::Result<()> {
|
||||
match Sys::fsync(self.0) {
|
||||
match Sys::fsync(self.fd) {
|
||||
-1 => Err(last_os_error()),
|
||||
_ok => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_len(&self, size: u64) -> io::Result<()> {
|
||||
match Sys::ftruncate(self.0, size as off_t) {
|
||||
match Sys::ftruncate(self.fd, size as off_t) {
|
||||
-1 => Err(last_os_error()),
|
||||
_ok => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
match Sys::dup(self.0) {
|
||||
match Sys::dup(self.fd) {
|
||||
-1 => Err(last_os_error()),
|
||||
ok => Ok(File(ok)),
|
||||
ok => Ok(Self::new(ok)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new file pointing to the same underlying descriptor. This file
|
||||
/// will know it's a "reference" and won't close the fd. It will, however,
|
||||
/// not prevent the original file from closing the fd.
|
||||
pub unsafe fn get_ref(&self) -> Self {
|
||||
Self {
|
||||
fd: self.fd,
|
||||
reference: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for File {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
match Sys::read(self.0, buf) {
|
||||
match Sys::read(self.fd, buf) {
|
||||
-1 => Err(last_os_error()),
|
||||
ok => Ok(ok as usize),
|
||||
}
|
||||
@@ -61,7 +84,7 @@ impl io::Read for File {
|
||||
|
||||
impl io::Write for File {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match Sys::write(self.0, buf) {
|
||||
match Sys::write(self.fd, buf) {
|
||||
-1 => Err(last_os_error()),
|
||||
ok => Ok(ok as usize),
|
||||
}
|
||||
@@ -80,9 +103,25 @@ impl io::Seek for File {
|
||||
io::SeekFrom::End(end) => (end as off_t, SEEK_END),
|
||||
};
|
||||
|
||||
match Sys::lseek(self.0, offset, whence) {
|
||||
match Sys::lseek(self.fd, offset, whence) {
|
||||
-1 => Err(last_os_error()),
|
||||
ok => Ok(ok as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for File {
|
||||
type Target = c_int;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for File {
|
||||
fn drop(&mut self) {
|
||||
if !self.reference {
|
||||
let _ = Sys::close(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use platform::types::*;
|
||||
|
||||
pub const EOF: c_int = -1;
|
||||
pub const BUFSIZ: size_t = 1024;
|
||||
|
||||
pub const UNGET: size_t = 8;
|
||||
|
||||
+22
-33
@@ -1,12 +1,28 @@
|
||||
use super::{constants, BUFSIZ, FILE, UNGET};
|
||||
use super::{constants, Buffer, BUFSIZ, FILE, UNGET};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::ptr;
|
||||
use core::sync::atomic::AtomicBool;
|
||||
|
||||
use fs::File;
|
||||
use io::LineWriter;
|
||||
use platform::types::*;
|
||||
|
||||
pub struct GlobalFile(UnsafeCell<FILE>);
|
||||
impl GlobalFile {
|
||||
const fn new(file: FILE) -> Self {
|
||||
GlobalFile(UnsafeCell::new(file))
|
||||
fn new(file: c_int, flags: c_int) -> Self {
|
||||
let file = File::new(file);
|
||||
let writer = LineWriter::new(unsafe { file.get_ref() });
|
||||
GlobalFile(UnsafeCell::new(FILE {
|
||||
lock: AtomicBool::new(false),
|
||||
|
||||
file,
|
||||
flags: constants::F_PERM | flags,
|
||||
read_buf: Buffer::Owned(vec![0; BUFSIZ]),
|
||||
read_pos: 0,
|
||||
read_size: 0,
|
||||
unget: None,
|
||||
writer
|
||||
}))
|
||||
}
|
||||
pub fn get(&self) -> *mut FILE {
|
||||
self.0.get()
|
||||
@@ -17,40 +33,13 @@ unsafe impl Sync for GlobalFile {}
|
||||
|
||||
lazy_static! {
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static ref default_stdin: GlobalFile = GlobalFile::new(FILE {
|
||||
flags: constants::F_PERM | constants::F_NOWR,
|
||||
read: None,
|
||||
write: None,
|
||||
fd: 0,
|
||||
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
|
||||
buf_char: -1,
|
||||
unget: UNGET,
|
||||
lock: AtomicBool::new(false),
|
||||
});
|
||||
pub static ref default_stdin: GlobalFile = GlobalFile::new(0, constants::F_NOWR);
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static ref default_stdout: GlobalFile = GlobalFile::new(FILE {
|
||||
flags: constants::F_PERM | constants::F_NORD,
|
||||
read: None,
|
||||
write: None,
|
||||
fd: 1,
|
||||
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
|
||||
buf_char: b'\n' as i8,
|
||||
unget: 0,
|
||||
lock: AtomicBool::new(false),
|
||||
});
|
||||
pub static ref default_stdout: GlobalFile = GlobalFile::new(1, constants::F_NORD);
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static ref default_stderr: GlobalFile = GlobalFile::new(FILE {
|
||||
flags: constants::F_PERM | constants::F_NORD,
|
||||
read: None,
|
||||
write: None,
|
||||
fd: 2,
|
||||
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
|
||||
buf_char: -1,
|
||||
unget: 0,
|
||||
lock: AtomicBool::new(false),
|
||||
});
|
||||
pub static ref default_stderr: GlobalFile = GlobalFile::new(2, constants::F_NORD);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
+19
-102
@@ -1,14 +1,17 @@
|
||||
use alloc::boxed::Box;
|
||||
use core::sync::atomic::AtomicBool;
|
||||
use core::{mem, ptr};
|
||||
|
||||
use fs::File;
|
||||
use header::errno;
|
||||
use header::fcntl::*;
|
||||
use header::string::strchr;
|
||||
use platform;
|
||||
use io::LineWriter;
|
||||
use platform::types::*;
|
||||
use platform;
|
||||
|
||||
use super::constants::*;
|
||||
use super::{BUFSIZ, FILE, UNGET};
|
||||
use super::{Buffer, FILE};
|
||||
|
||||
/// Parse mode flags as a string and output a mode flags integer
|
||||
pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
|
||||
@@ -61,104 +64,18 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
|
||||
flags |= F_APP;
|
||||
}
|
||||
|
||||
let f = platform::alloc(mem::size_of::<FILE>()) as *mut FILE;
|
||||
// Allocate the file
|
||||
if f.is_null() {
|
||||
None
|
||||
} else {
|
||||
ptr::write(
|
||||
f,
|
||||
FILE {
|
||||
flags: flags,
|
||||
read: None,
|
||||
write: None,
|
||||
fd: fd,
|
||||
buf: vec![0u8; BUFSIZ + UNGET],
|
||||
buf_char: -1,
|
||||
unget: UNGET,
|
||||
lock: AtomicBool::new(false),
|
||||
},
|
||||
);
|
||||
Some(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write buffer `buf` of length `l` into `stream`
|
||||
pub fn fwritex(buf: *const u8, l: size_t, stream: &mut FILE) -> size_t {
|
||||
use core::ptr::copy_nonoverlapping;
|
||||
use core::slice;
|
||||
|
||||
let buf: &'static [u8] = unsafe { slice::from_raw_parts(buf, l) };
|
||||
let mut l = l;
|
||||
let mut advance = 0;
|
||||
|
||||
if stream.write.is_none() && !stream.can_write() {
|
||||
// We can't write to this stream
|
||||
return 0;
|
||||
}
|
||||
if let Some((wbase, mut wpos, wend)) = stream.write {
|
||||
if l > wend - wpos {
|
||||
// We can't fit all of buf in the buffer
|
||||
return stream.write(buf);
|
||||
}
|
||||
|
||||
let i = if stream.buf_char >= 0 {
|
||||
let mut i = l;
|
||||
while i > 0 && buf[i - 1] != b'\n' {
|
||||
i -= 1;
|
||||
}
|
||||
if i > 0 {
|
||||
let n = stream.write(buf);
|
||||
match stream.write {
|
||||
Some((_, new_wpos, _)) => wpos = new_wpos,
|
||||
None => unreachable!("stream.write should never be None after a write call")
|
||||
}
|
||||
|
||||
if n < i {
|
||||
return n;
|
||||
}
|
||||
advance += i;
|
||||
l -= i;
|
||||
}
|
||||
i
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
unsafe {
|
||||
copy_nonoverlapping(
|
||||
&buf[advance..] as *const _ as *const u8,
|
||||
&mut stream.buf[wpos..] as *mut _ as *mut u8,
|
||||
l,
|
||||
);
|
||||
}
|
||||
stream.write = Some((wbase, wpos + l, wend));
|
||||
l + i
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Flush `stream` without locking it.
|
||||
pub fn fflush_unlocked(stream: &mut FILE) -> c_int {
|
||||
if let Some((wbase, wpos, _)) = stream.write {
|
||||
if wpos > wbase {
|
||||
stream.write(&[]);
|
||||
/*
|
||||
if stream.wpos.is_null() {
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((rpos, rend)) = stream.read {
|
||||
if rpos < rend {
|
||||
stream.seek(rpos as i64 - rend as i64, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
stream.write = None;
|
||||
stream.read = None;
|
||||
0
|
||||
let file = File::new(fd);
|
||||
let writer = LineWriter::new(file.get_ref());
|
||||
|
||||
Some(Box::into_raw(Box::new(FILE {
|
||||
lock: AtomicBool::new(false),
|
||||
|
||||
file,
|
||||
flags,
|
||||
read_buf: Buffer::Owned(vec![0; BUFSIZ as usize]),
|
||||
read_pos: 0,
|
||||
read_size: 0,
|
||||
unget: None,
|
||||
writer
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
use super::{constants, FILE};
|
||||
use platform::types::*;
|
||||
|
||||
pub fn ftello(stream: &mut FILE) -> off_t {
|
||||
let pos = stream.seek(
|
||||
0,
|
||||
if let Some((wbase, wpos, _)) = stream.write {
|
||||
if (stream.flags & constants::F_APP > 0) && wpos > wbase {
|
||||
constants::SEEK_END
|
||||
} else {
|
||||
constants::SEEK_CUR
|
||||
}
|
||||
} else {
|
||||
constants::SEEK_CUR
|
||||
},
|
||||
);
|
||||
if pos < 0 {
|
||||
return pos;
|
||||
}
|
||||
let rdiff = if let Some((rpos, rend)) = stream.read {
|
||||
rend - rpos
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let wdiff = if let Some((wbase, wpos, _)) = stream.write {
|
||||
wpos - wbase
|
||||
} else {
|
||||
0
|
||||
};
|
||||
pos - rdiff as i64 + wdiff as i64
|
||||
}
|
||||
//use super::{constants, FILE};
|
||||
//use platform::types::*;
|
||||
//
|
||||
//pub fn ftello(stream: &mut FILE) -> off_t {
|
||||
// let pos = stream.seek(
|
||||
// 0,
|
||||
// if let Some((wbase, wpos, _)) = stream.write {
|
||||
// if (stream.flags & constants::F_APP > 0) && wpos > wbase {
|
||||
// constants::SEEK_END
|
||||
// } else {
|
||||
// constants::SEEK_CUR
|
||||
// }
|
||||
// } else {
|
||||
// constants::SEEK_CUR
|
||||
// },
|
||||
// );
|
||||
// if pos < 0 {
|
||||
// return pos;
|
||||
// }
|
||||
// let rdiff = if let Some((rpos, rend)) = stream.read {
|
||||
// rend - rpos
|
||||
// } else {
|
||||
// 0
|
||||
// };
|
||||
// let wdiff = if let Some((wbase, wpos, _)) = stream.write {
|
||||
// wpos - wbase
|
||||
// } else {
|
||||
// 0
|
||||
// };
|
||||
// pos - rdiff as i64 + wdiff as i64
|
||||
//}
|
||||
|
||||
+317
-481
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
use alloc::String;
|
||||
use alloc::Vec;
|
||||
use io::Read;
|
||||
use platform::types::*;
|
||||
use platform::ReadByte;
|
||||
use va_list::VaList;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
@@ -27,7 +27,7 @@ unsafe fn next_byte(string: &mut *const c_char) -> Result<u8, c_int> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn inner_scanf<R: ReadByte>(
|
||||
unsafe fn inner_scanf<R: Read>(
|
||||
mut r: R,
|
||||
mut format: *const c_char,
|
||||
mut ap: VaList,
|
||||
@@ -39,14 +39,15 @@ unsafe fn inner_scanf<R: ReadByte>(
|
||||
|
||||
macro_rules! read {
|
||||
() => {{
|
||||
match r.read_u8() {
|
||||
Ok(Some(b)) => {
|
||||
byte = b;
|
||||
let mut buf = &mut [byte];
|
||||
match r.read(buf) {
|
||||
Ok(0) => false,
|
||||
Ok(_) => {
|
||||
byte = buf[0];
|
||||
count += 1;
|
||||
true
|
||||
}
|
||||
Ok(None) => false,
|
||||
Err(()) => return Err(-1),
|
||||
Err(_) => return Err(-1),
|
||||
}
|
||||
}};
|
||||
}
|
||||
@@ -420,7 +421,7 @@ unsafe fn inner_scanf<R: ReadByte>(
|
||||
}
|
||||
Ok(matched)
|
||||
}
|
||||
pub unsafe fn scanf<R: ReadByte>(r: R, format: *const c_char, ap: VaList) -> c_int {
|
||||
pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: VaList) -> c_int {
|
||||
match inner_scanf(r, format, ap) {
|
||||
Ok(n) => n,
|
||||
Err(n) => n,
|
||||
|
||||
+17
-38
@@ -1,5 +1,6 @@
|
||||
use alloc::vec::Vec;
|
||||
use core::{fmt, ptr};
|
||||
use io::{self, Read};
|
||||
|
||||
pub use self::allocator::*;
|
||||
|
||||
@@ -70,16 +71,6 @@ impl<'a, W: WriteByte> WriteByte for &'a mut W {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ReadByte {
|
||||
fn read_u8(&mut self) -> Result<Option<u8>, ()>;
|
||||
}
|
||||
|
||||
impl<'a, R: ReadByte> ReadByte for &'a mut R {
|
||||
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
|
||||
(**self).read_u8()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileWriter(pub c_int);
|
||||
|
||||
impl FileWriter {
|
||||
@@ -110,13 +101,13 @@ impl FileReader {
|
||||
}
|
||||
}
|
||||
|
||||
impl ReadByte for FileReader {
|
||||
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
|
||||
let mut buf = [0];
|
||||
match self.read(&mut buf) {
|
||||
0 => Ok(None),
|
||||
n if n < 0 => Err(()),
|
||||
_ => Ok(Some(buf[0])),
|
||||
impl Read for FileReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let i = Sys::read(self.0, buf);
|
||||
if i >= 0 {
|
||||
Ok(i as usize)
|
||||
} else {
|
||||
Err(io::Error::from_raw_os_error(-i as i32))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,32 +173,20 @@ impl WriteByte for UnsafeStringWriter {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StringReader<'a>(pub &'a [u8]);
|
||||
|
||||
impl<'a> ReadByte for StringReader<'a> {
|
||||
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
|
||||
if self.0.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
let byte = self.0[0];
|
||||
self.0 = &self.0[1..];
|
||||
Ok(Some(byte))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnsafeStringReader(pub *const u8);
|
||||
|
||||
impl ReadByte for UnsafeStringReader {
|
||||
fn read_u8(&mut self) -> Result<Option<u8>, ()> {
|
||||
impl Read for UnsafeStringReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
if *self.0 == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
let byte = *self.0;
|
||||
for i in 0..buf.len() {
|
||||
if *self.0 == 0 {
|
||||
return Ok(i);
|
||||
}
|
||||
|
||||
buf[i] = *self.0;
|
||||
self.0 = self.0.offset(1);
|
||||
Ok(Some(byte))
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ EXPECT_BINS=\
|
||||
signal \
|
||||
stdio/all \
|
||||
stdio/buffer \
|
||||
stdio/fgets \
|
||||
stdio/freopen \
|
||||
stdio/fwrite \
|
||||
stdio/getc_unget \
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
//FILE *f = fopen("/etc/ssl/certs/ca-certificates.crt", "r");
|
||||
FILE *f = fopen("stdio/stdio.in", "r");
|
||||
char line[256];
|
||||
|
||||
while (1) {
|
||||
if (fgets(line, 256, f)) {
|
||||
fputs(line, stdout);
|
||||
} else {
|
||||
puts("EOF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,30 @@
|
||||
Hello World!
|
||||
|
||||
Line 2
|
||||
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
|
||||
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
|
||||
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
|
||||
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
|
||||
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
|
||||
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
|
||||
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
|
||||
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
|
||||
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
|
||||
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
|
||||
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
|
||||
|
||||
Reference in New Issue
Block a user