~noskcaj/ubuntu/trusty/gpgme1.0/1.4.3

« back to all changes in this revision

Viewing changes to src/w32-glib-io.c

  • Committer: Bazaar Package Importer
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2009-09-08 14:30:11 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090908143011-dv8rzfraejhex6t5
Tags: 1.2.0-1
* New Upstream Version (Closes: #545671)
* As there are new symbols introduced in this version, bump shlibs info. 
* Bump Standards-Version to 3.8.3, no changes. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
80
80
 
81
81
static struct 
82
82
{
 
83
  int used;
 
84
 
 
85
  /* If this is not -1, then it's a libc file descriptor.  */
 
86
  int fd;
 
87
  /* If fd is -1, this is the Windows socket handle.  */
 
88
  int socket;
 
89
 
83
90
  GIOChannel *chan;
84
91
  /* The boolean PRIMARY is true if this file descriptor caused the
85
92
     allocation of CHAN.  Only then should CHAN be destroyed when this
102
109
 
103
110
 
104
111
static GIOChannel *
105
 
find_channel (int fd, int create)
 
112
find_channel (int fd)
106
113
{
107
114
  if (fd < 0 || fd >= MAX_SLAFD)
108
115
    return NULL;
109
116
 
110
 
  if (create && !giochannel_table[fd].chan)
111
 
    {
112
 
      giochannel_table[fd].chan = g_io_channel_win32_new_fd (fd);
113
 
      giochannel_table[fd].primary = 1;
114
 
      g_io_channel_set_encoding (giochannel_table[fd].chan, NULL, NULL);
115
 
      g_io_channel_set_buffered (giochannel_table[fd].chan, FALSE);
116
 
    }
117
 
 
118
117
  return giochannel_table[fd].chan;
119
118
}
120
119
 
121
120
 
 
121
/* Returns the FD or -1 on resource limit.  */
 
122
int
 
123
new_dummy_channel_from_fd (int cfd)
 
124
{
 
125
  int idx;
 
126
 
 
127
  for (idx = 0; idx < MAX_SLAFD; idx++)
 
128
    if (! giochannel_table[idx].used)
 
129
      break;
 
130
 
 
131
  if (idx == MAX_SLAFD)
 
132
    {
 
133
      errno = EIO;
 
134
      return -1;
 
135
    }
 
136
 
 
137
  giochannel_table[idx].used = 1;
 
138
  giochannel_table[idx].chan = NULL;
 
139
  giochannel_table[idx].fd = cfd;
 
140
  giochannel_table[idx].socket = INVALID_SOCKET;
 
141
  giochannel_table[idx].primary = 1;
 
142
 
 
143
  return idx;
 
144
}
 
145
 
 
146
 
 
147
/* Returns the FD or -1 on resource limit.  */
 
148
int
 
149
new_channel_from_fd (int cfd)
 
150
{
 
151
  int idx;
 
152
 
 
153
  for (idx = 0; idx < MAX_SLAFD; idx++)
 
154
    if (! giochannel_table[idx].used)
 
155
      break;
 
156
 
 
157
  if (idx == MAX_SLAFD)
 
158
    {
 
159
      errno = EIO;
 
160
      return -1;
 
161
    }
 
162
 
 
163
  giochannel_table[idx].used = 1;
 
164
  giochannel_table[idx].chan = g_io_channel_win32_new_fd (cfd);
 
165
  giochannel_table[idx].fd = cfd;
 
166
  giochannel_table[idx].socket = INVALID_SOCKET;
 
167
  giochannel_table[idx].primary = 1;
 
168
 
 
169
  g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
 
170
  g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
 
171
 
 
172
  return idx;
 
173
}
 
174
 
 
175
 
 
176
/* Returns the FD or -1 on resource limit.  */
 
177
int
 
178
new_channel_from_socket (int sock)
 
179
{
 
180
  int idx;
 
181
 
 
182
  for (idx = 0; idx < MAX_SLAFD; idx++)
 
183
    if (! giochannel_table[idx].used)
 
184
      break;
 
185
 
 
186
  if (idx == MAX_SLAFD)
 
187
    {
 
188
      errno = EIO;
 
189
      return -1;
 
190
    }
 
191
 
 
192
  giochannel_table[idx].used = 1;
 
193
  giochannel_table[idx].chan = g_io_channel_win32_new_socket (sock);
 
194
  giochannel_table[idx].fd = -1;
 
195
  giochannel_table[idx].socket = sock;
 
196
  giochannel_table[idx].primary = 1;
 
197
 
 
198
  g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
 
199
  g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
 
200
 
 
201
  return idx;
 
202
}
 
203
 
 
204
 
122
205
/* Compatibility interface.  Obsolete.  */
123
206
void *
124
207
gpgme_get_giochannel (int fd)
125
208
{
126
 
  return find_channel (fd, 0);
 
209
  return find_channel (fd);
127
210
}
128
211
 
129
212
 
131
214
void *
132
215
gpgme_get_fdptr (int fd)
133
216
{
134
 
  return find_channel (fd, 0);
 
217
  return find_channel (fd);
135
218
}
136
219
 
137
220
 
141
224
int
142
225
_gpgme_io_fd2str (char *buf, int buflen, int fd)
143
226
{
 
227
  HANDLE hndl;
 
228
    
144
229
  TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd);
145
 
  TRACE_SUC1 ("syshd=%p", _get_osfhandle (fd));
146
 
  return snprintf (buf, buflen, "%d", (int) _get_osfhandle (fd));
 
230
  if (giochannel_table[fd].fd != -1)
 
231
    hndl = (HANDLE) _get_osfhandle (giochannel_table[fd].fd);
 
232
  else
 
233
    hndl = (HANDLE) giochannel_table[fd].socket;
 
234
 
 
235
  TRACE_SUC1 ("syshd=%p", hndl);
 
236
  
 
237
  return snprintf (buf, buflen, "%d", (int) hndl);
147
238
}
148
239
 
149
240
 
170
261
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
171
262
              "buffer=%p, count=%u", buffer, count);
172
263
 
173
 
  chan = find_channel (fd, 0);
 
264
  chan = find_channel (fd);
174
265
  if (!chan)
175
266
    {
176
267
      TRACE_LOG ("no channel registered");
192
283
 
193
284
  if (status == G_IO_STATUS_EOF)
194
285
    nread = 0;
 
286
  else if (status == G_IO_STATUS_AGAIN)
 
287
    {
 
288
      nread = -1;
 
289
      saved_errno = EAGAIN;
 
290
    }
195
291
  else if (status != G_IO_STATUS_NORMAL)
196
292
    {
197
293
      TRACE_LOG1 ("status %d", status);
198
294
      nread = -1;
199
295
      saved_errno = EIO;
200
296
    }
201
 
 
202
 
  TRACE_LOGBUF (buffer, nread);
 
297
  
 
298
  if (nread != 0 && nread != -1)
 
299
    TRACE_LOGBUF (buffer, nread);
203
300
 
204
301
  errno = saved_errno;
205
302
  return TRACE_SYSRES (nread);
213
310
  gsize nwritten;
214
311
  GIOChannel *chan;
215
312
  GIOStatus status;
 
313
  GError *err = NULL;
 
314
 
216
315
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
217
316
              "buffer=%p, count=%u", buffer, count);
218
317
  TRACE_LOGBUF (buffer, count);
219
318
 
220
 
  chan = find_channel (fd, 0);
 
319
  chan = find_channel (fd);
221
320
  if (!chan)
222
321
    {
223
322
      TRACE_LOG ("fd %d: no channel registered");
226
325
    }
227
326
 
228
327
  status = g_io_channel_write_chars (chan, (gchar *) buffer, count,
229
 
                                     &nwritten, NULL);
230
 
  if (status != G_IO_STATUS_NORMAL)
 
328
                                     &nwritten, &err);
 
329
  if (err)
 
330
    {
 
331
      TRACE_LOG1 ("write error: %s", err->message);
 
332
      g_error_free (err);
 
333
    }
 
334
 
 
335
  if (status == G_IO_STATUS_AGAIN)
 
336
    {
 
337
      nwritten = -1;
 
338
      saved_errno = EAGAIN;
 
339
    }
 
340
  else if (status != G_IO_STATUS_NORMAL)
231
341
    {
232
342
      nwritten = -1;
233
343
      saved_errno = EIO;
241
351
int
242
352
_gpgme_io_pipe (int filedes[2], int inherit_idx)
243
353
{
244
 
  GIOChannel *chan;
 
354
  int fds[2];
 
355
 
245
356
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
246
357
              "inherit_idx=%i (GPGME uses it for %s)",
247
358
              inherit_idx, inherit_idx ? "reading" : "writing");
248
359
 
249
360
#define PIPEBUF_SIZE  4096
250
 
  if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
 
361
  if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
251
362
    return TRACE_SYSRES (-1);
252
363
 
253
364
  /* Make one end inheritable. */
255
366
    {
256
367
      int new_read;
257
368
 
258
 
      new_read = _dup (filedes[0]);
259
 
      _close (filedes[0]);
260
 
      filedes[0] = new_read;
 
369
      new_read = _dup (fds[0]);
 
370
      _close (fds[0]);
 
371
      fds[0] = new_read;
261
372
 
262
373
      if (new_read < 0)
263
374
        {
264
 
          _close (filedes[1]);
 
375
          _close (fds[1]);
265
376
          return TRACE_SYSRES (-1);
266
377
        }
267
378
    }
269
380
    {
270
381
      int new_write;
271
382
 
272
 
      new_write = _dup (filedes[1]);
273
 
      _close (filedes[1]);
274
 
      filedes[1] = new_write;
 
383
      new_write = _dup (fds[1]);
 
384
      _close (fds[1]);
 
385
      fds[1] = new_write;
275
386
 
276
387
      if (new_write < 0)
277
388
        {
278
 
          _close (filedes[0]);
 
389
          _close (fds[0]);
279
390
          return TRACE_SYSRES (-1);
280
391
        }
281
392
    }
282
393
 
283
 
  /* Now we have a pipe with the right end inheritable.  The other end
 
394
  /* For _gpgme_io_close.  */
 
395
  filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]);
 
396
  if (filedes[inherit_idx] < 0)
 
397
    {
 
398
      int saved_errno = errno;
 
399
      
 
400
      _close (fds[0]);
 
401
      _close (fds[1]);
 
402
      errno = saved_errno;
 
403
      return TRACE_SYSRES (-1);
 
404
    }
 
405
 
 
406
  /* Now we have a pipe with the correct end inheritable.  The other end
284
407
     should have a giochannel.  */
285
 
  chan = find_channel (filedes[1 - inherit_idx], 1);
286
 
  if (!chan)
 
408
  filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]);
 
409
  if (filedes[1 - inherit_idx] < 0)
287
410
    {
288
411
      int saved_errno = errno;
289
 
      _close (filedes[0]);
290
 
      _close (filedes[1]);
 
412
      
 
413
      _gpgme_io_close (fds[inherit_idx]);
 
414
      _close (fds[1 - inherit_idx]);
291
415
      errno = saved_errno;
292
416
      return TRACE_SYSRES (-1);
293
417
    }
294
 
 
 
418
  
295
419
  return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
296
 
          filedes[0], (HANDLE) _get_osfhandle (filedes[0]),
297
 
          filedes[1], (HANDLE) _get_osfhandle (filedes[1]),
298
 
          chan);
 
420
                     filedes[0],
 
421
                     (HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd),
 
422
                     filedes[1],
 
423
                     (HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd),
 
424
                     giochannel_table[1 - inherit_idx].chan);
299
425
}
300
426
 
301
427
 
310
436
      return TRACE_SYSRES (-1);
311
437
    }
312
438
 
 
439
  assert (giochannel_table[fd].used);
 
440
 
313
441
  /* First call the notify handler.  */
314
442
  if (notify_table[fd].handler)
315
443
    {
318
446
      notify_table[fd].value = NULL;
319
447
    }
320
448
 
321
 
  /* Then do the close.  */    
 
449
  /* Then do the close.  */
322
450
  if (giochannel_table[fd].chan)
323
451
    {
324
452
      if (giochannel_table[fd].primary)
325
453
        g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL);
326
 
      else
327
 
        _close (fd);
328
 
 
 
454
      
329
455
      g_io_channel_unref (giochannel_table[fd].chan);
330
 
      giochannel_table[fd].chan = NULL;
331
456
    }
332
457
  else
333
 
    _close (fd);
 
458
    {
 
459
      /* Dummy entry, just close.  */
 
460
      assert (giochannel_table[fd].fd != -1);
 
461
      _close (giochannel_table[fd].fd);
 
462
    }
 
463
        
 
464
  giochannel_table[fd].used = 0;
 
465
  giochannel_table[fd].fd = -1;
 
466
  giochannel_table[fd].socket = INVALID_SOCKET;
 
467
  giochannel_table[fd].chan = NULL;
 
468
  giochannel_table[fd].primary = 0;
334
469
 
335
470
  TRACE_SUC ();
336
471
  return 0;
365
500
 
366
501
  TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
367
502
 
368
 
  chan = find_channel (fd, 0);
 
503
  chan = find_channel (fd);
369
504
  if (!chan)
370
505
    {
371
506
      errno = EIO;
372
507
      return TRACE_SYSRES (-1);
373
508
    }
374
509
 
375
 
   status = g_io_channel_set_flags (chan,
 
510
  status = g_io_channel_set_flags (chan,
376
511
                                   g_io_channel_get_flags (chan) |
377
512
                                   G_IO_FLAG_NONBLOCK, NULL);
 
513
 
378
514
  if (status != G_IO_STATUS_NORMAL)
379
515
    {
380
516
#if 0
448
584
 
449
585
 
450
586
int
451
 
_gpgme_io_spawn (const char *path, char **argv,
 
587
_gpgme_io_spawn (const char *path, char * const argv[], unsigned int flags,
452
588
                 struct spawn_fd_item_s *fd_list, pid_t *r_pid)
453
589
{
454
590
  SECURITY_ATTRIBUTES sec_attr;
460
596
      0          /* returns tid */
461
597
    };
462
598
  STARTUPINFO si;
463
 
  int cr_flags = CREATE_DEFAULT_ERROR_MODE
464
 
    | GetPriorityClass (GetCurrentProcess ());
 
599
  int cr_flags = (CREATE_DEFAULT_ERROR_MODE
 
600
                  | GetPriorityClass (GetCurrentProcess ()));
465
601
  int i;
466
602
  char **args;
467
603
  char *arg_string;
543
679
 
544
680
  free (arg_string);
545
681
  
 
682
  if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
 
683
    _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
 
684
 
546
685
  /* Insert the inherited handles.  */
547
686
  for (i = 0; fd_list[i].fd != -1; i++)
548
687
    {
549
688
      HANDLE hd;
550
689
 
551
690
      /* Make it inheritable for the wrapper process.  */
552
 
      if (!DuplicateHandle (GetCurrentProcess(), _get_osfhandle (fd_list[i].fd),
 
691
      if (!DuplicateHandle (GetCurrentProcess(),
 
692
                            _get_osfhandle (giochannel_table[fd_list[i].fd].fd),
553
693
                            pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
554
694
        {
555
695
          TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
584
724
    int written;
585
725
    size_t len;
586
726
 
587
 
    line[0] = '\n';
588
 
    line[1] = '\0';
 
727
    if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
 
728
      strcpy (line, "~1 \n");
 
729
    else
 
730
      strcpy (line, "\n");
589
731
    for (i = 0; fd_list[i].fd != -1; i++)
590
732
      {
591
733
        /* Strip the newline.  */
694
836
        continue;
695
837
 
696
838
      if ((fds[i].for_read || fds[i].for_write)
697
 
          && !(chan = find_channel (fds[i].fd, 0)))
 
839
          && !(chan = find_channel (fds[i].fd)))
698
840
        {
699
841
          TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd);
700
842
          TRACE_END (dbg_help, "]"); 
786
928
{
787
929
  int newfd;
788
930
  GIOChannel *chan;
 
931
 
 
932
  TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
 
933
 
 
934
  if (fd < 0 || fd >= MAX_SLAFD || !giochannel_table[fd].used)
 
935
    {
 
936
      errno = EINVAL;
 
937
      return TRACE_SYSRES (-1);
 
938
    }
 
939
 
 
940
  for (newfd = 0; newfd < MAX_SLAFD; newfd++)
 
941
    if (! giochannel_table[newfd].used)
 
942
      break;
 
943
  if (newfd == MAX_SLAFD)
 
944
    {
 
945
      errno = EIO;
 
946
      return TRACE_SYSRES (-1);
 
947
    }
789
948
  
790
 
  TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd);
791
 
 
792
 
  newfd = _dup (fd);
793
 
  if (newfd == -1)
794
 
    return TRACE_SYSRES (-1);
795
 
  if (newfd < 0 || newfd >= MAX_SLAFD)
796
 
    {
797
 
      /* New FD won't fit into our table.  */
798
 
      _close (newfd);
799
 
      errno = EIO; 
800
 
      return TRACE_SYSRES (-1);
801
 
    }
802
 
  assert (giochannel_table[newfd].chan == NULL);
803
 
 
804
 
  chan = find_channel (fd, 0);
805
 
  assert (chan);
806
 
 
 
949
  chan = giochannel_table[fd].chan;
807
950
  g_io_channel_ref (chan);
 
951
  giochannel_table[newfd].used = 1;
808
952
  giochannel_table[newfd].chan = chan;
 
953
  giochannel_table[newfd].fd = -1;
 
954
  giochannel_table[newfd].socket = INVALID_SOCKET;
809
955
  giochannel_table[newfd].primary = 0;
810
956
 
811
957
  return TRACE_SYSRES (newfd);
812
958
}
 
959
 
 
960
 
 
961
 
 
962
 
 
963
 
 
964
static int
 
965
wsa2errno (int err)
 
966
{
 
967
  switch (err)
 
968
    {
 
969
    case WSAENOTSOCK:
 
970
      return EINVAL;
 
971
    case WSAEWOULDBLOCK:
 
972
      return EAGAIN;
 
973
    case ERROR_BROKEN_PIPE:
 
974
      return EPIPE;
 
975
    case WSANOTINITIALISED:
 
976
      return ENOSYS;
 
977
    default:
 
978
      return EIO;
 
979
    }
 
980
}
 
981
 
 
982
 
 
983
int
 
984
_gpgme_io_socket (int domain, int type, int proto)
 
985
{
 
986
  int res;
 
987
  int fd;
 
988
 
 
989
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
 
990
              "type=%i, protp=%i", type, proto);
 
991
 
 
992
  res = socket (domain, type, proto);
 
993
  if (res == INVALID_SOCKET)
 
994
    {
 
995
      errno = wsa2errno (WSAGetLastError ());
 
996
      return TRACE_SYSRES (-1);
 
997
    }
 
998
 
 
999
  fd = new_channel_from_socket (res);
 
1000
  if (fd < 0)
 
1001
    {
 
1002
      int saved_errno = errno;
 
1003
      closesocket (res);
 
1004
      errno = saved_errno;
 
1005
      return TRACE_SYSRES (-1);
 
1006
    }
 
1007
 
 
1008
  TRACE_SUC2 ("fd=%i, socket=0x%x", fd, res);
 
1009
  
 
1010
  return fd;
 
1011
}
 
1012
 
 
1013
 
 
1014
int
 
1015
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
 
1016
{
 
1017
  GIOChannel *chan; 
 
1018
  int sockfd;
 
1019
  int res;
 
1020
  GIOFlags flags;
 
1021
  GIOStatus status;
 
1022
  GError *err = NULL;
 
1023
 
 
1024
  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
 
1025
              "addr=%p, addrlen=%i", addr, addrlen);
 
1026
 
 
1027
  chan = find_channel (fd);
 
1028
  if (! chan)
 
1029
    {
 
1030
      errno = EINVAL;
 
1031
      return TRACE_SYSRES (-1);
 
1032
    }
 
1033
 
 
1034
  flags = g_io_channel_get_flags (chan);
 
1035
  if (flags & G_IO_FLAG_NONBLOCK)
 
1036
    {
 
1037
      status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err);
 
1038
      if (err)
 
1039
        {
 
1040
          TRACE_LOG1 ("setting flags error: %s", err->message);
 
1041
          g_error_free (err);
 
1042
          err = NULL;
 
1043
        }
 
1044
      if (status != G_IO_STATUS_NORMAL)
 
1045
        {
 
1046
          errno = EIO;
 
1047
          return TRACE_SYSRES (-1);
 
1048
        }
 
1049
    }
 
1050
 
 
1051
  sockfd = giochannel_table[fd].socket;
 
1052
  if (sockfd == INVALID_SOCKET)
 
1053
    {
 
1054
      errno = EINVAL;
 
1055
      return TRACE_SYSRES (-1);
 
1056
    }
 
1057
 
 
1058
  TRACE_LOG1 ("connect sockfd=0x%x", sockfd);
 
1059
  res = connect (sockfd, addr, addrlen);
 
1060
 
 
1061
  /* FIXME: Error ignored here.  */
 
1062
  if (! (flags & G_IO_FLAG_NONBLOCK))
 
1063
    g_io_channel_set_flags (chan, flags, NULL);
 
1064
 
 
1065
  if (res)
 
1066
    {
 
1067
      TRACE_LOG2 ("connect failed: %i %i", res, WSAGetLastError ());
 
1068
 
 
1069
      errno = wsa2errno (WSAGetLastError ());
 
1070
      return TRACE_SYSRES (-1);
 
1071
    }
 
1072
 
 
1073
  return TRACE_SUC ();
 
1074
}