This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3] Final fix for libstdc++/13731


Hi,

the below fixes the second part (unsafe writev). I'm committing to
mainline only but this is a regression from 3.3, therefore after
some days of testing both patches will go to 3_4-branch too.

Tested x86-linux.

Paolo.

///////////
2004-02-12  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/13731 (final part: writev)
	* config/io/basic_file_stdio.cc (__gnu_internal::xwrite):
	New, a wrapper around writev() handling partial writes.
	(__basic_file<char>::xwrite): Move to __gnu_internal and make
	static.
	(__basic_file<char>::xsputn): Update call.
	(__basic_file<char>::xsputn_2): Likewise.	
	* config/io/basic_file_stdio.h (__basic_file<char>::write):
	Don't declare, now static.
diff -prN libstdc++-v3-orig/config/io/basic_file_stdio.cc libstdc++-v3/config/io/basic_file_stdio.cc
*** libstdc++-v3-orig/config/io/basic_file_stdio.cc	Thu Feb 12 01:01:03 2004
--- libstdc++-v3/config/io/basic_file_stdio.cc	Thu Feb 12 12:53:29 2004
*************** namespace __gnu_internal
*** 105,110 ****
--- 105,164 ----
        default: return 0; // invalid
        }
    }
+ 
+   // Wrapper handling partial write.
+   static std::streamsize
+   xwrite(int __fd, const char* __s, std::streamsize __n)
+   {
+     std::streamsize __nleft = __n;
+     while (__nleft > 0)
+       {
+ 	const std::streamsize __ret = write(__fd, __s, __nleft);
+ 	if (__ret == -1L && errno == EINTR)
+ 	  continue;
+ 	else if (__ret == -1L)
+ 	  break;
+ 	__nleft -= __ret;
+ 	__s += __ret;
+       }
+     return __n - __nleft;
+   }
+ 
+ #ifdef _GLIBCXX_HAVE_WRITEV
+   // Wrapper handling partial writev.
+   static std::streamsize
+   xwritev(int __fd, const char* __s1, std::streamsize __n1,
+ 	  const char* __s2, std::streamsize __n2)
+   {
+     std::streamsize __ret;
+ 
+     struct iovec __iov[2];
+     __iov[0].iov_base = const_cast<char*>(__s1);
+     __iov[0].iov_len = __n1;
+     __iov[1].iov_base = const_cast<char*>(__s2);
+     __iov[1].iov_len = __n2;
+ 
+     do
+       __ret = writev(__fd, __iov, 2);
+     while (__ret == -1L && errno == EINTR);
+ 
+     if (__ret == -1L)
+       __ret = 0;
+     else if (__ret < __n1 + __n2)
+       {
+ 	if (__ret >= __n1)
+ 	  {
+ 	    const std::streamsize __off = __ret - __n1;
+ 	    __ret += xwrite(__fd, __s2 + __off, __n2 - __off);
+ 	  }
+ 	else
+ 	  __ret += xwritev(__fd, __s1 + __ret, __n1 - __ret,
+ 			   __s2, __n2);
+       }
+ 
+     return __ret;
+   }
+ #endif
  } // namespace __gnu_internal
  
  namespace std 
*************** namespace std 
*** 201,227 ****
      return __ret;
    }
  
-   // Wrapper handling partial write.
-   streamsize
-   __basic_file<char>::xwrite(const char* __s, streamsize __n)
-   {
-     streamsize __nleft = __n;
-     while (__nleft > 0)
-       {
- 	const streamsize __ret = write(this->fd(), __s, __nleft);
- 	if (__ret == -1L && errno == EINTR)
- 	  continue;
- 	else if (__ret == -1L)
- 	  break;
- 	__nleft -= __ret;
- 	__s += __ret;
-       }
-     return __n - __nleft;
-   }
-  
    streamsize 
    __basic_file<char>::xsputn(const char* __s, streamsize __n)
!   { return __basic_file<char>::xwrite(__s, __n); }
  
    streamsize 
    __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
--- 255,263 ----
      return __ret;
    }
  
    streamsize 
    __basic_file<char>::xsputn(const char* __s, streamsize __n)
!   { return __gnu_internal::xwrite(this->fd(), __s, __n); }
  
    streamsize 
    __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
*************** namespace std 
*** 229,249 ****
    {
      streamsize __ret = 0;
  #ifdef _GLIBCXX_HAVE_WRITEV
!     struct iovec __iov[2];
!     __iov[0].iov_base = const_cast<char*>(__s1);
!     __iov[0].iov_len = __n1;
!     __iov[1].iov_base = const_cast<char*>(__s2);
!     __iov[1].iov_len = __n2;
! 
!     do
!       __ret = writev(this->fd(), __iov, 2);
!     while (__ret == -1L && errno == EINTR);
  #else
      if (__n1)
!       __ret = __basic_file<char>::xwrite(__s1, __n1);
  
      if (__ret == __n1)
!       __ret += __basic_file<char>::xwrite(__s2, __n2);
  #endif
      return __ret;
    }
--- 265,277 ----
    {
      streamsize __ret = 0;
  #ifdef _GLIBCXX_HAVE_WRITEV
!     __ret = __gnu_internal::xwritev(this->fd(), __s1, __n1, __s2, __n2);
  #else
      if (__n1)
!       __ret = __gnu_internal::xwrite(this->fd(), __s1, __n1);
  
      if (__ret == __n1)
!       __ret += __gnu_internal::xwrite(this->fd(), __s2, __n2);
  #endif
      return __ret;
    }
diff -prN libstdc++-v3-orig/config/io/basic_file_stdio.h libstdc++-v3/config/io/basic_file_stdio.h
*** libstdc++-v3-orig/config/io/basic_file_stdio.h	Wed Feb 11 17:59:49 2004
--- libstdc++-v3/config/io/basic_file_stdio.h	Thu Feb 12 12:51:55 2004
*************** namespace std 
*** 84,92 ****
        ~__basic_file();
  
        streamsize 
-       xwrite(const char* __s, streamsize __n);
- 
-       streamsize 
        xsputn(const char* __s, streamsize __n);
  
        streamsize 
--- 84,89 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]