File: io_trywrite.c

package info (click to toggle)
libowfat 0.34-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,288 kB
  • sloc: ansic: 20,181; makefile: 16
file content (131 lines) | stat: -rw-r--r-- 3,478 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <unistd.h>
#include <sys/time.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <poll.h>
#endif
#include <errno.h>
#include "io_internal.h"

#ifdef __MINGW32__
#include <stdio.h>

/* All the Unix trickery is unsupported on Windows.  Instead, one is
 * supposed to do the whole write in overlapping mode and then get
 * notified via an I/O completion port when it's done. */

/* So we assume io_trywrite is not used so much and do the overlapping
 * stuff on I/O batches. */

int64 io_trywrite(int64 d,const char* buf,int64 len) {
  io_entry* e=iarray_get(&io_fds,d);
  int r;
  if (!e) { errno=EBADF; return -3; }
  if (!e->nonblock) {
    DWORD written;
    fprintf(stderr,"Socket is in blocking mode, just calling WriteFile...");
    if (WriteFile((HANDLE)d,buf,len,&written,0)) {
      fprintf(stderr," OK, got %u bytes.\n",written);
      return written;
    } else {
      fprintf(stderr," failed.\n",written);
      return winsock2errno(-3);
    }
  } else {
    if (e->writequeued && !e->canwrite) {
      fprintf(stderr,"io_trywrite: write already queued, returning EAGAIN\n");
      errno=EAGAIN;
      return -1;
    }
    if (e->canwrite) {
      e->canwrite=0;
      e->next_write=-1;
      if (e->errorcode) {
	fprintf(stderr,"io_trywrite: e->canwrite was set, returning error %d\n",e->errorcode);
	errno=winsock2errno(e->errorcode);
	return -3;
      }
      fprintf(stderr,"io_trywrite: e->canwrite was set, had written %u bytes\n",e->bytes_written);
      return e->bytes_written;
    } else {
      fprintf(stderr,"io_trywrite: queueing write...");
      if (WriteFile((HANDLE)d,buf,len,&e->errorcode,&e->ow)) {
	fprintf(stderr," worked unexpectedly, error %d\n",e->errorcode);
	return e->errorcode; /* should not happen */
      } else if (GetLastError()==ERROR_IO_PENDING) {
	fprintf(stderr," pending.\n");
	e->writequeued=1;
	errno=EAGAIN;
	e->errorcode=0;
	return -1;
      } else {
	fprintf(stderr," failed, error %d\n",e->errorcode);
	winsock2errno(-1);
	e->errorcode=errno;
	return -3;
      }
    }
  }
}

#else

int64 io_trywrite(int64 d,const char* buf,int64 len) {
  long r;
  struct itimerval old,new;
  struct pollfd p;
  io_entry* e=iarray_get(&io_fds,d);
  io_sigpipe();
  if (!e) { errno=EBADF; return -3; }
  if (!e->nonblock) {
    p.fd=d;
    if (p.fd != d) { errno=EBADF; return -3; }	/* catch overflow */
    p.events=POLLOUT;
    switch (poll(&p,1,0)) {
    case -1: return -3;
    case 0: errno=EAGAIN;
	    e->canwrite=0;
	    e->next_write=-1;
	    return -1;
    }
    new.it_interval.tv_usec=10000;
    new.it_interval.tv_sec=0;
    new.it_value.tv_usec=10000;
    new.it_value.tv_sec=0;
    setitimer(ITIMER_REAL,&new,&old);
  }
  r=write(d,buf,len);
  if (!e->nonblock) {
    setitimer(ITIMER_REAL,&old,0);
  }
  if (r==-1 && errno==EAGAIN)
    io_eagain_write(d);
  if (r==-1) {
    if (errno==EINTR) errno=EAGAIN;
    if (errno!=EAGAIN)
      r=-3;
  }
  if (r!=len) {
    e->canwrite=0;
    io_eagain_write(d);
#if defined(HAVE_SIGIO)
    if (d==alt_firstwrite) {
#if 0
      debug_printf(("io_trywrite: dequeueing %ld from alt write queue (next is %ld)\n",d,e->next_write));
      alt_firstwrite=e->next_write;
      e->next_write=-1;
#else
      if (d==alt_curwrite) alt_curwrite=-1;
    } else {
      debug_printf(("io_trywrite: enqueueing %ld into alt write queue (next is %ld)\n",d,alt_firstwrite));
      e->next_write=alt_firstwrite;
      alt_firstwrite=d;
#endif
    }
#endif
  }
  return r;
}

#endif