diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 8901a98b569a230609f4b8fbe97ef6a98046dd9f..75d729b482143b66bc00e1268f749719a77abc54 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,10 @@
+2003-02-17  Paolo Carlini  <pcarlini@unitus.it>
+
+	PR libstdc++/9169
+	* include/bits/fstream.tcc (_M_convert_to_external):
+	Deal correctly with noconv, as prescribed by 27.8.1.4,p8.
+	* testsuite/27_io/filebuf_virtuals.cc (test10): Add.
+
 2003-02-13  Benjamin Kosnik  <bkoz@redhat.com>
 
 	* include/bits/c++config (_GLIBCPP_EXTERN_TEMPLATE): Define.
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index 2c591c389a2011cc450fc0527539a7a18b044528..0c6e7b04b6bf16cbdca7fff4d2386a50f1a2df62 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -291,9 +291,15 @@ namespace std
 	  const char_type* __iend;
 	  __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen, 
 		 		     __iend, __buf, __buf + __blen, __bend);
-	  // Result == ok, partial, noconv
-	  if (__r != codecvt_base::error)
+
+	  if (__r == codecvt_base::ok || __r == codecvt_base::partial)
 	    __blen = __bend - __buf;
+	  // Similarly to the always_noconv case above.
+	  else if (__r == codecvt_base::noconv)
+	    {
+	      __buf = reinterpret_cast<char*>(__ibuf);
+	      __blen = __ilen;
+	    }
 	  // Result == error
 	  else 
 	    __blen = 0;
diff --git a/libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc b/libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc
index 3090f315912d88a2067bfd2b7c666331ca8aab26..843038aab482381e7eec4cebb137139a985dc8bd 100644
--- a/libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc
+++ b/libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc
@@ -584,6 +584,46 @@ void test09()
   VERIFY( r == filebuf::traits_type::eof() );
 }
 
+class Cvt_to_upper : public std::codecvt<char, char, mbstate_t>
+{
+  bool do_always_noconv() const throw()
+  {
+    return false;
+  }
+};
+
+// libstdc++/9169
+void test10()
+{
+  using namespace std;
+  bool test = true;
+
+  locale c_loc;
+  locale loc(c_loc, new Cvt_to_upper);
+
+  string str("abcdefghijklmnopqrstuvwxyz");
+  string tmp;
+
+  {
+    ofstream out;
+    out.imbue(loc);
+    out.open("filebuf_virtuals-4.txt");
+    copy(str.begin(), str.end(),
+	 ostreambuf_iterator<char>(out));
+  }
+
+  {
+    ifstream in;
+    in.open("filebuf_virtuals-4.txt");
+    copy(istreambuf_iterator<char>(in),
+	 istreambuf_iterator<char>(),
+	 back_inserter(tmp));
+  }
+
+  VERIFY( tmp.size() == str.size() );
+  VERIFY( tmp == str );
+}
+
 main() 
 {
   test01();
@@ -597,5 +637,6 @@ main()
   test07();
   test08();
   test09();
+  test10();
   return 0;
 }