Index: uspace/lib/posix/source/stdio.c
===================================================================
--- uspace/lib/posix/source/stdio.c	(revision 6afc9d780e775e54c1cfb5d3c57fb749979b18d2)
+++ uspace/lib/posix/source/stdio.c	(revision e3c960e1bdab0baa0afb2fefa5847dedc0fac870)
@@ -55,4 +55,10 @@
 #include "libc/sys/stat.h"
 
+
+/* not the best of solutions, but freopen and ungetc will eventually
+ * need to be implemented in libc anyway
+ */
+#include "../../c/generic/private/stdio.h"
+
 /** Clears the stream's error and end-of-file indicators.
  *
@@ -61,5 +67,6 @@
 void posix_clearerr(FILE *stream)
 {
-	clearerr(stream);
+	stream->error = 0;
+	stream->eof = 0;
 }
 
@@ -94,5 +101,10 @@
 int posix_fputs(const char *restrict s, FILE *restrict stream)
 {
-	return fputs(s, stream);
+	int rc = fputs(s, stream);
+	if (rc == 0) {
+		return EOF;
+	} else {
+		return 0;
+	}
 }
 
@@ -106,5 +118,33 @@
 int posix_ungetc(int c, FILE *stream)
 {
-	return ungetc(c, stream);
+	uint8_t b = (uint8_t) c;
+
+	bool can_unget =
+	    /* Provided character is legal. */
+	    c != EOF &&
+	    /* Stream is consistent. */
+	    !stream->error &&
+	    /* Stream is buffered. */
+	    stream->btype != _IONBF &&
+	    /* Last operation on the stream was a read operation. */
+	    stream->buf_state == _bs_read &&
+	    /* Stream buffer is already allocated (i.e. there was already carried
+	     * out either write or read operation on the stream). This is probably
+	     * redundant check but let's be safe. */
+	    stream->buf != NULL &&
+	    /* There is still space in the stream to retreat. POSIX demands the
+	     * possibility to unget at least 1 character. It should be always
+	     * possible, assuming the last operation on the stream read at least 1
+	     * character, because the buffer is refilled in the lazily manner. */
+	    stream->buf_tail > stream->buf;
+
+	if (can_unget) {
+		--stream->buf_tail;
+		stream->buf_tail[0] = b;
+		stream->eof = false;
+		return (int) b;
+	} else {
+		return EOF;
+	}
 }
 
@@ -214,5 +254,43 @@
     const char *restrict mode, FILE *restrict stream)
 {
-	return freopen(filename, mode, stream);
+	assert(mode != NULL);
+	assert(stream != NULL);
+	
+	if (filename == NULL) {
+		/* POSIX allows this to be imlementation-defined. HelenOS currently
+		 * does not support changing the mode. */
+		// FIXME: handle mode change once it is supported
+		return stream;
+	}
+	
+	/* Open a new stream. */
+	FILE* new = fopen(filename, mode);
+	if (new == NULL) {
+		fclose(stream);
+		/* errno was set by fopen() */
+		return NULL;
+	}
+	
+	/* Close the original stream without freeing it (ignoring errors). */
+	if (stream->buf != NULL) {
+		fflush(stream);
+	}
+	if (stream->sess != NULL) {
+		async_hangup(stream->sess);
+	}
+	if (stream->fd >= 0) {
+		close(stream->fd);
+	}
+	list_remove(&stream->link);
+	
+	/* Move the new stream to the original location. */
+	memcpy(stream, new, sizeof (FILE));
+	free(new);
+	
+	/* Update references in the file list. */
+	stream->link.next->prev = &stream->link;
+	stream->link.prev->next = &stream->link;
+	
+	return stream;
 }
 
@@ -315,5 +393,11 @@
 int posix_fflush(FILE *stream)
 {
-	return negerrno(fflush, stream);
+	int rc = fflush(stream);
+	if (rc < 0) {
+		errno = -rc;
+		return EOF;
+	} else {
+		return 0;
+	}
 }
 
@@ -345,6 +429,4 @@
 {
 	ssize_t wr = write(*(int *) fd, str, size);
-	if (wr < 0)
-		return errno;
 	return str_nlength(str, wr);
 }
@@ -575,5 +657,23 @@
 int posix_remove(const char *path)
 {
-	return negerrno(remove, path);
+	struct stat st;
+	int rc = stat(path, &st);
+	
+	if (rc != EOK) {
+		errno = -rc;
+		return -1;
+	}
+	
+	if (st.is_directory) {
+		rc = rmdir(path);
+	} else {
+		rc = unlink(path);
+	}
+	
+	if (rc != EOK) {
+		errno = -rc;
+		return -1;
+	}
+	return 0;
 }
 
@@ -587,5 +687,5 @@
 int posix_rename(const char *old, const char *new)
 {
-	return negerrno(rename, old, new);
+	return errnify(rename, old, new);
 }
 
