write.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:7k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: write.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 20:35:53  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #include "tds.h"
  29. #include "tdsutil.h"
  30. #include <signal.h> /* GW ADDED */
  31. #ifdef DMALLOC
  32. #include <dmalloc.h>
  33. #endif
  34. #ifdef WIN32
  35. #define WRITE(a,b,c) send((a),(b),(c), 0L)
  36. #else 
  37. #define WRITE(a,b,c) write(a,b,c)
  38. #endif
  39. static char  software_version[]   = "$Id: write.c,v 1000.0 2003/10/29 20:35:53 gouriano Exp $";
  40. static void *no_unused_var_warn[] = {software_version,
  41.                                      no_unused_var_warn};
  42. /*
  43.  * CRE 01262002 making buf a void * means we can put any type without casting
  44.  * much like read() and memcpy()
  45.  */
  46. int
  47. tds_put_n(TDSSOCKET *tds, const unsigned char *buf, int n)
  48. {
  49. #ifdef NCBI_FTDS
  50. int left,to_copy;
  51. while(n > 0){
  52. left = tds->env->block_size - tds->out_pos;
  53. if (left <= 0){
  54. tds_write_packet(tds,0x0);
  55. tds_init_write_buf(tds);
  56.          left = tds->env->block_size - tds->out_pos;
  57. }
  58. to_copy = (n < left)?n:left;
  59. if(buf){
  60. memcpy(tds->out_buf+tds->out_pos,buf,to_copy);
  61. buf+=to_copy;
  62. } else {
  63. memset(tds->out_buf+tds->out_pos,'',to_copy);
  64. }
  65. tds->out_pos+=to_copy;
  66. n-=to_copy;
  67. if(to_copy == 0 && tds->s == 0) break;
  68. }
  69. #else
  70. int i;
  71. const unsigned char *bufp = buf;
  72. if (bufp)  {
  73. for (i=0;i<n;i++)
  74. tds_put_byte(tds, bufp[i]);
  75. } else {
  76. for (i=0;i<n;i++)
  77. tds_put_byte(tds, '');
  78. }
  79. #endif
  80. return 0;
  81. }
  82. int tds_put_string(TDSSOCKET *tds, const char *buf, int n)
  83. {
  84. int buf_len = ( buf ? strlen(buf) : 0);
  85. return tds_put_buf(tds,(const unsigned char *)buf,n,buf_len);
  86. }
  87. int tds_put_buf(TDSSOCKET *tds, const unsigned char *buf, int dsize, int ssize)
  88. {
  89. int  cpsize;
  90. cpsize = ssize > dsize ? dsize : ssize;
  91. tds_put_n(tds,buf,cpsize);
  92. dsize -= cpsize;
  93. tds_put_n(tds,NULL,dsize);
  94. return tds_put_byte(tds,cpsize);
  95. }
  96. int tds_put_int(TDSSOCKET *tds, TDS_INT i)
  97. {
  98. #if WORDS_BIGENDIAN
  99. if (tds->emul_little_endian) {
  100. tds_put_byte(tds, i & 0x000000FF);
  101. tds_put_byte(tds, (i & 0x0000FF00) >> 8);
  102. tds_put_byte(tds, (i & 0x00FF0000) >> 16);
  103. tds_put_byte(tds, (i & 0xFF000000) >> 24);
  104. return 0;
  105. }
  106. #endif
  107. return tds_put_n(tds,(const unsigned char *)&i,sizeof(TDS_INT));
  108. }
  109. int tds_put_smallint(TDSSOCKET *tds, TDS_SMALLINT si)
  110. {
  111. #if WORDS_BIGENDIAN
  112. if (tds->emul_little_endian) {
  113. tds_put_byte(tds, si & 0x000000FF);
  114. tds_put_byte(tds, (si & 0x0000FF00) >> 8);
  115. return 0;
  116. }
  117. #endif
  118. return tds_put_n(tds,(const unsigned char *)&si,sizeof(TDS_SMALLINT));
  119. }
  120. int tds_put_tinyint(TDSSOCKET *tds, TDS_TINYINT ti)
  121. {
  122. return tds_put_byte(tds,(unsigned char)ti);
  123. }
  124. int tds_put_byte(TDSSOCKET *tds, unsigned char c)
  125. {
  126. if (tds->out_pos >= tds->env->block_size) {
  127. tds_write_packet(tds,0x0);
  128. tds_init_write_buf(tds);
  129. }
  130. tds->out_buf[tds->out_pos++]=c;
  131. return 0;
  132. }
  133. int tds_put_bulk_data(TDSSOCKET *tds, const unsigned char * buf, TDS_INT bufsize)
  134. {
  135. tds->out_flag = 0x07;
  136. return tds_put_n(tds,buf,bufsize);
  137. }
  138. int tds_init_write_buf(TDSSOCKET *tds)
  139. {
  140. memset(tds->out_buf,'',tds->env->block_size);
  141. tds->out_pos=8;
  142. return 0;
  143. }
  144. /* TODO this code should be similar to read one... */
  145. static int 
  146. tds_check_socket_write(TDSSOCKET *tds)
  147. {
  148. int retcode = 0;
  149. struct timeval selecttimeout;
  150. time_t start, now;
  151. fd_set fds;
  152.  
  153. /* Jeffs hack *** START OF NEW CODE */
  154. FD_ZERO (&fds);
  155. if (!tds->timeout) {
  156. for(;;) {
  157. FD_SET (tds->s, &fds);
  158. retcode = select (tds->s + 1, NULL, &fds, NULL, NULL);
  159. /* write available */
  160. if (retcode >= 0) return 0;
  161. /* interrupted */
  162. if (errno == EINTR) continue;
  163. /* error, leave caller handle problems*/
  164. return -1;
  165. }
  166. }
  167. start = time(NULL);
  168. now = start;
  169.  
  170. while ((retcode == 0) && ((now-start) < tds->timeout)) {
  171. FD_SET (tds->s, &fds);
  172. selecttimeout.tv_sec = tds->timeout - (now-start);
  173. selecttimeout.tv_usec = 0;
  174. retcode = select (tds->s + 1, NULL, &fds, NULL, &selecttimeout);
  175. if (retcode < 0 && errno == EINTR) {
  176. retcode = 0;
  177. }
  178. now = time (NULL);
  179. }
  180.  
  181. return retcode;
  182. /* Jeffs hack *** END OF NEW CODE */
  183. }
  184. /* goodwrite function adapted from patch by freddy77 */
  185. static int
  186. goodwrite(TDSSOCKET *tds)
  187. {
  188. int left;
  189. char *p;
  190. int result = 1;
  191. int retval;
  192. left = tds->out_pos;
  193. p = tds->out_buf;
  194.   
  195. while (left > 0) {
  196. /* If there's a timeout, we need to sit and wait for socket */
  197. /* writability */
  198. /* moved socket writability check to own function -- bsb */
  199. tds_check_socket_write(tds);
  200. retval = WRITE(tds->s,p,left);
  201. if (retval <= 0) {
  202. tdsdump_log(TDS_DBG_NETWORK, "TDS: Write failed in tds_write_packetnError: %d (%s)n", errno, strerror(errno));
  203. tds_client_msg(tds->tds_ctx, tds, 10018, 9, 0, 0, "The connection was closed");
  204. tds->in_pos=0;
  205. tds->in_len=0;
  206. close(tds->s);
  207. tds->s=0;
  208. result = 0;
  209. break;
  210. }
  211. left -= retval;
  212. p += retval;
  213. }
  214. return result;
  215. }
  216. int tds_write_packet(TDSSOCKET *tds,unsigned char final)
  217. {
  218. int retcode;
  219. void (*oldsig)(int);
  220. tds->out_buf[0]=tds->out_flag;
  221. tds->out_buf[1]=final;
  222. #ifdef NCBI_FTDS
  223. tds->out_buf[2]=(tds->out_pos) >> 8;
  224. tds->out_buf[3]=(tds->out_pos) & 0xFF;
  225. #else
  226. tds->out_buf[2]=(tds->out_pos)/256u;
  227. tds->out_buf[3]=(tds->out_pos)%256u;
  228. #endif
  229. if (IS_TDS70(tds) || IS_TDS80(tds)) {
  230. tds->out_buf[6]=0x01;
  231. }
  232. tdsdump_log(TDS_DBG_NETWORK, "Sending packet @ %Ln%Dn", tds->out_buf, tds->out_pos);
  233. #ifdef NCBI_FTDS
  234.    tds_block_sigpipe();
  235. #else
  236. oldsig=signal (SIGPIPE, SIG_IGN);
  237. if (oldsig==SIG_ERR) {
  238. tdsdump_log(TDS_DBG_WARN, "TDS: Warning: Couldn't set SIGPIPE signal to be ignoredn");
  239. }
  240. #endif
  241. retcode=goodwrite(tds);
  242. #ifdef NCBI_FTDS
  243.    tds_reset_sigpipe();
  244. #else
  245. if (signal(SIGPIPE, oldsig)==SIG_ERR) {
  246. tdsdump_log(TDS_DBG_WARN, "TDS: Warning: Couldn't reset SIGPIPE signal to previous valuen");
  247. }
  248. #endif
  249. /* GW added in check for write() returning <0 and SIGPIPE checking */
  250. return retcode;
  251. }
  252. int tds_flush_packet(TDSSOCKET *tds)
  253. {
  254. if (tds->s) {
  255. tds_write_packet(tds,0x01);
  256. tds_init_write_buf(tds);
  257. }
  258. /* GW added check for tds->s */
  259. return 0;
  260. }