Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 7db5cfdf9880d55d20d1c9ff67cdd1d2890e72f1)
+++ uspace/lib/c/generic/io/io.c	(revision 80bee816e04fc95402bcb3439cb9262667a14574)
@@ -299,5 +299,6 @@
 }
 
-int fclose(FILE *stream)
+
+static int _fclose_nofree(FILE *stream)
 {
 	int rc = 0;
@@ -312,4 +313,16 @@
 	
 	list_remove(&stream->link);
+	
+	if (rc != 0) {
+		/* errno was set by close() */
+		return EOF;
+	}
+	
+	return 0;
+}
+
+int fclose(FILE *stream)
+{
+	int rc = _fclose_nofree(stream);
 	
 	if ((stream != &stdin_null)
@@ -318,12 +331,30 @@
 		free(stream);
 	
-	stream = NULL;
-	
-	if (rc != 0) {
-		/* errno was set by close() */
-		return EOF;
-	}
-	
-	return 0;
+	return rc;
+}
+
+FILE *freopen(const char *path, const char *mode, FILE *stream)
+{
+	FILE *nstr;
+	
+	if (path == NULL) {
+		/* Changing mode is not supported */
+		return NULL;
+	}
+	
+	(void) _fclose_nofree(stream);
+	nstr = fopen(path, mode);
+	if (nstr == NULL) {
+		free(stream);
+		return NULL;
+	}
+	
+	list_remove(&nstr->link);
+	*stream = *nstr;
+	list_append(&stream->link, &files);
+	
+	free(nstr);
+	
+	return stream;
 }
 
Index: uspace/lib/c/include/stdio.h
===================================================================
--- uspace/lib/c/include/stdio.h	(revision 7db5cfdf9880d55d20d1c9ff67cdd1d2890e72f1)
+++ uspace/lib/c/include/stdio.h	(revision 80bee816e04fc95402bcb3439cb9262667a14574)
@@ -134,4 +134,5 @@
 extern FILE *fopen(const char *, const char *);
 extern FILE *fdopen(int, const char *);
+extern FILE *freopen(const char *, const char *, FILE *);
 extern int fclose(FILE *);
 
Index: uspace/lib/posix/source/stdio.c
===================================================================
--- uspace/lib/posix/source/stdio.c	(revision 7db5cfdf9880d55d20d1c9ff67cdd1d2890e72f1)
+++ uspace/lib/posix/source/stdio.c	(revision 80bee816e04fc95402bcb3439cb9262667a14574)
@@ -55,10 +55,4 @@
 #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.
  *
@@ -67,6 +61,5 @@
 void posix_clearerr(FILE *stream)
 {
-	stream->error = 0;
-	stream->eof = 0;
+	clearerr(stream);
 }
 
@@ -221,43 +214,5 @@
     const char *restrict mode, FILE *restrict 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;
+	return freopen(filename, mode, stream);
 }
 
