Coverage Report

Created: 2025-11-24 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/irssi/subprojects/glib-2.74.3/glib/giounix.c
Line
Count
Source
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3
 *
4
 * giounix.c: IO Channels using unix file descriptors
5
 * Copyright 1998 Owen Taylor
6
 *
7
 * SPDX-License-Identifier: LGPL-2.1-or-later
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/*
24
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
25
 * file for a list of people on the GLib Team.  See the ChangeLog
26
 * files for a list of changes.  These files are distributed with
27
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
28
 */
29
30
/*
31
 * MT safe
32
 */
33
34
#include "config.h"
35
36
#define _POSIX_SOURCE   /* for SSIZE_MAX */
37
38
#include <sys/types.h>
39
#include <sys/stat.h>
40
#include <stdio.h>
41
#include <unistd.h>
42
#include <errno.h>
43
#include <string.h>
44
#include <fcntl.h>
45
#include <glib/gstdio.h>
46
47
#include "giochannel.h"
48
49
#include "gerror.h"
50
#include "gfileutils.h"
51
#include "gstrfuncs.h"
52
#include "gtestutils.h"
53
54
/*
55
 * Unix IO Channels
56
 */
57
58
typedef struct _GIOUnixChannel GIOUnixChannel;
59
typedef struct _GIOUnixWatch GIOUnixWatch;
60
61
struct _GIOUnixChannel
62
{
63
  GIOChannel channel;
64
  gint fd;
65
};
66
67
struct _GIOUnixWatch
68
{
69
  GSource       source;
70
  GPollFD       pollfd;
71
  GIOChannel   *channel;
72
  GIOCondition  condition;
73
};
74
75
76
static GIOStatus  g_io_unix_read    (GIOChannel   *channel,
77
             gchar        *buf,
78
             gsize         count,
79
             gsize        *bytes_read,
80
             GError      **err);
81
static GIOStatus  g_io_unix_write   (GIOChannel   *channel,
82
             const gchar  *buf,
83
             gsize         count,
84
             gsize        *bytes_written,
85
             GError      **err);
86
static GIOStatus  g_io_unix_seek    (GIOChannel   *channel,
87
             gint64        offset,
88
             GSeekType     type,
89
             GError      **err);
90
static GIOStatus  g_io_unix_close   (GIOChannel   *channel,
91
             GError      **err);
92
static void   g_io_unix_free    (GIOChannel   *channel);
93
static GSource*   g_io_unix_create_watch  (GIOChannel   *channel,
94
             GIOCondition  condition);
95
static GIOStatus  g_io_unix_set_flags (GIOChannel   *channel,
96
                               GIOFlags      flags,
97
             GError      **err);
98
static GIOFlags   g_io_unix_get_flags (GIOChannel   *channel);
99
100
static gboolean g_io_unix_prepare  (GSource     *source,
101
            gint        *timeout);
102
static gboolean g_io_unix_check    (GSource     *source);
103
static gboolean g_io_unix_dispatch (GSource     *source,
104
            GSourceFunc  callback,
105
            gpointer     user_data);
106
static void     g_io_unix_finalize (GSource     *source);
107
108
GSourceFuncs g_io_watch_funcs = {
109
  g_io_unix_prepare,
110
  g_io_unix_check,
111
  g_io_unix_dispatch,
112
  g_io_unix_finalize,
113
  NULL, NULL
114
};
115
116
static GIOFuncs unix_channel_funcs = {
117
  g_io_unix_read,
118
  g_io_unix_write,
119
  g_io_unix_seek,
120
  g_io_unix_close,
121
  g_io_unix_create_watch,
122
  g_io_unix_free,
123
  g_io_unix_set_flags,
124
  g_io_unix_get_flags,
125
};
126
127
static gboolean 
128
g_io_unix_prepare (GSource  *source,
129
       gint     *timeout)
130
0
{
131
0
  GIOUnixWatch *watch = (GIOUnixWatch *)source;
132
0
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
133
134
0
  *timeout = -1;
135
136
  /* Only return TRUE here if _all_ bits in watch->condition will be set
137
   */
138
0
  return ((watch->condition & buffer_condition) == watch->condition);
139
0
}
140
141
static gboolean 
142
g_io_unix_check (GSource  *source)
143
0
{
144
0
  GIOUnixWatch *watch = (GIOUnixWatch *)source;
145
0
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
146
0
  GIOCondition poll_condition = watch->pollfd.revents;
147
148
0
  return ((poll_condition | buffer_condition) & watch->condition);
149
0
}
150
151
static gboolean
152
g_io_unix_dispatch (GSource     *source,
153
        GSourceFunc  callback,
154
        gpointer     user_data)
155
156
0
{
157
0
  GIOFunc func = (GIOFunc)callback;
158
0
  GIOUnixWatch *watch = (GIOUnixWatch *)source;
159
0
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
160
161
0
  if (!func)
162
0
    {
163
0
      g_warning ("IO watch dispatched without callback. "
164
0
     "You must call g_source_connect().");
165
0
      return FALSE;
166
0
    }
167
  
168
0
  return (*func) (watch->channel,
169
0
      (watch->pollfd.revents | buffer_condition) & watch->condition,
170
0
      user_data);
171
0
}
172
173
static void 
174
g_io_unix_finalize (GSource *source)
175
0
{
176
0
  GIOUnixWatch *watch = (GIOUnixWatch *)source;
177
178
0
  g_io_channel_unref (watch->channel);
179
0
}
180
181
static GIOStatus
182
g_io_unix_read (GIOChannel *channel, 
183
    gchar      *buf, 
184
    gsize       count,
185
    gsize      *bytes_read,
186
    GError    **err)
187
47.6k
{
188
47.6k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
189
47.6k
  gssize result;
190
191
47.6k
  if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
192
0
    count = SSIZE_MAX;
193
194
47.6k
 retry:
195
47.6k
  result = read (unix_channel->fd, buf, count);
196
197
47.6k
  if (result < 0)
198
0
    {
199
0
      int errsv = errno;
200
0
      *bytes_read = 0;
201
202
0
      switch (errsv)
203
0
        {
204
0
#ifdef EINTR
205
0
          case EINTR:
206
0
            goto retry;
207
0
#endif
208
0
#ifdef EAGAIN
209
0
          case EAGAIN:
210
0
            return G_IO_STATUS_AGAIN;
211
0
#endif
212
0
          default:
213
0
            g_set_error_literal (err, G_IO_CHANNEL_ERROR,
214
0
                                 g_io_channel_error_from_errno (errsv),
215
0
                                 g_strerror (errsv));
216
0
            return G_IO_STATUS_ERROR;
217
0
        }
218
0
    }
219
220
47.6k
  *bytes_read = result;
221
222
47.6k
  return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
223
47.6k
}
224
225
static GIOStatus
226
g_io_unix_write (GIOChannel  *channel, 
227
     const gchar *buf, 
228
     gsize       count,
229
     gsize      *bytes_written,
230
     GError    **err)
231
9.49k
{
232
9.49k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
233
9.49k
  gssize result;
234
235
9.49k
 retry:
236
9.49k
  result = write (unix_channel->fd, buf, count);
237
238
9.49k
  if (result < 0)
239
7.82k
    {
240
7.82k
      int errsv = errno;
241
7.82k
      *bytes_written = 0;
242
243
7.82k
      switch (errsv)
244
7.82k
        {
245
0
#ifdef EINTR
246
0
          case EINTR:
247
0
            goto retry;
248
0
#endif
249
0
#ifdef EAGAIN
250
0
          case EAGAIN:
251
0
            return G_IO_STATUS_AGAIN;
252
0
#endif
253
7.82k
          default:
254
7.82k
            g_set_error_literal (err, G_IO_CHANNEL_ERROR,
255
7.82k
                                 g_io_channel_error_from_errno (errsv),
256
7.82k
                                 g_strerror (errsv));
257
7.82k
            return G_IO_STATUS_ERROR;
258
7.82k
        }
259
7.82k
    }
260
261
1.66k
  *bytes_written = result;
262
263
1.66k
  return G_IO_STATUS_NORMAL;
264
9.49k
}
265
266
static GIOStatus
267
g_io_unix_seek (GIOChannel *channel,
268
    gint64      offset, 
269
    GSeekType   type,
270
                GError    **err)
271
2.38k
{
272
2.38k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
273
2.38k
  int whence;
274
2.38k
  off_t tmp_offset;
275
2.38k
  off_t result;
276
277
2.38k
  switch (type)
278
2.38k
    {
279
2.38k
    case G_SEEK_SET:
280
2.38k
      whence = SEEK_SET;
281
2.38k
      break;
282
0
    case G_SEEK_CUR:
283
0
      whence = SEEK_CUR;
284
0
      break;
285
0
    case G_SEEK_END:
286
0
      whence = SEEK_END;
287
0
      break;
288
0
    default:
289
0
      whence = -1; /* Shut the compiler up */
290
0
      g_assert_not_reached ();
291
2.38k
    }
292
293
2.38k
  tmp_offset = offset;
294
2.38k
  if (tmp_offset != offset)
295
0
    {
296
0
      g_set_error_literal (err, G_IO_CHANNEL_ERROR,
297
0
                           g_io_channel_error_from_errno (EINVAL),
298
0
                           g_strerror (EINVAL));
299
0
      return G_IO_STATUS_ERROR;
300
0
    }
301
  
302
2.38k
  result = lseek (unix_channel->fd, tmp_offset, whence);
303
304
2.38k
  if (result < 0)
305
0
    {
306
0
      int errsv = errno;
307
0
      g_set_error_literal (err, G_IO_CHANNEL_ERROR,
308
0
                           g_io_channel_error_from_errno (errsv),
309
0
                           g_strerror (errsv));
310
0
      return G_IO_STATUS_ERROR;
311
0
    }
312
313
2.38k
  return G_IO_STATUS_NORMAL;
314
2.38k
}
315
316
317
static GIOStatus
318
g_io_unix_close (GIOChannel *channel,
319
     GError    **err)
320
81.3k
{
321
81.3k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
322
323
81.3k
  if (close (unix_channel->fd) < 0)
324
39.2k
    {
325
39.2k
      int errsv = errno;
326
39.2k
      g_set_error_literal (err, G_IO_CHANNEL_ERROR,
327
39.2k
                           g_io_channel_error_from_errno (errsv),
328
39.2k
                           g_strerror (errsv));
329
39.2k
      return G_IO_STATUS_ERROR;
330
39.2k
    }
331
332
42.0k
  return G_IO_STATUS_NORMAL;
333
81.3k
}
334
335
static void 
336
g_io_unix_free (GIOChannel *channel)
337
42.0k
{
338
42.0k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
339
340
42.0k
  g_free (unix_channel);
341
42.0k
}
342
343
static GSource *
344
g_io_unix_create_watch (GIOChannel   *channel,
345
      GIOCondition  condition)
346
422
{
347
422
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
348
422
  GSource *source;
349
422
  GIOUnixWatch *watch;
350
351
352
422
  source = g_source_new (&g_io_watch_funcs, sizeof (GIOUnixWatch));
353
422
  g_source_set_static_name (source, "GIOChannel (Unix)");
354
422
  watch = (GIOUnixWatch *)source;
355
  
356
422
  watch->channel = channel;
357
422
  g_io_channel_ref (channel);
358
  
359
422
  watch->condition = condition;
360
361
422
  watch->pollfd.fd = unix_channel->fd;
362
422
  watch->pollfd.events = condition;
363
364
422
  g_source_add_poll (source, &watch->pollfd);
365
366
422
  return source;
367
422
}
368
369
static GIOStatus
370
g_io_unix_set_flags (GIOChannel *channel,
371
                     GIOFlags    flags,
372
                     GError    **err)
373
7.93k
{
374
7.93k
  glong fcntl_flags;
375
7.93k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
376
377
7.93k
  fcntl_flags = 0;
378
379
7.93k
  if (flags & G_IO_FLAG_APPEND)
380
0
    fcntl_flags |= O_APPEND;
381
7.93k
  if (flags & G_IO_FLAG_NONBLOCK)
382
0
#ifdef O_NONBLOCK
383
0
    fcntl_flags |= O_NONBLOCK;
384
#else
385
    fcntl_flags |= O_NDELAY;
386
#endif
387
388
7.93k
  if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
389
7.82k
    {
390
7.82k
      int errsv = errno;
391
7.82k
      g_set_error_literal (err, G_IO_CHANNEL_ERROR,
392
7.82k
                           g_io_channel_error_from_errno (errsv),
393
7.82k
                           g_strerror (errsv));
394
7.82k
      return G_IO_STATUS_ERROR;
395
7.82k
    }
396
397
107
  return G_IO_STATUS_NORMAL;
398
7.93k
}
399
400
static GIOFlags
401
g_io_unix_get_flags (GIOChannel *channel)
402
48.0k
{
403
48.0k
  GIOFlags flags = G_IO_FLAG_NONE;
404
48.0k
  glong fcntl_flags;
405
48.0k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
406
407
48.0k
  fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
408
409
48.0k
  if (fcntl_flags == -1)
410
7.82k
    {
411
7.82k
      int err = errno;
412
7.82k
      g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)",
413
7.82k
     g_strerror (err), err);
414
7.82k
      return 0;
415
7.82k
    }
416
417
40.1k
  if (fcntl_flags & O_APPEND)
418
0
    flags |= G_IO_FLAG_APPEND;
419
40.1k
#ifdef O_NONBLOCK
420
40.1k
  if (fcntl_flags & O_NONBLOCK)
421
#else
422
  if (fcntl_flags & O_NDELAY)
423
#endif
424
0
    flags |= G_IO_FLAG_NONBLOCK;
425
426
40.1k
  switch (fcntl_flags & (O_RDONLY | O_WRONLY | O_RDWR))
427
40.1k
    {
428
0
      case O_RDONLY:
429
0
        channel->is_readable = TRUE;
430
0
        channel->is_writeable = FALSE;
431
0
        break;
432
0
      case O_WRONLY:
433
0
        channel->is_readable = FALSE;
434
0
        channel->is_writeable = TRUE;
435
0
        break;
436
40.1k
      case O_RDWR:
437
40.1k
        channel->is_readable = TRUE;
438
40.1k
        channel->is_writeable = TRUE;
439
40.1k
        break;
440
0
      default:
441
0
        g_assert_not_reached ();
442
40.1k
    }
443
444
40.1k
  return flags;
445
40.1k
}
446
447
GIOChannel *
448
g_io_channel_new_file (const gchar *filename,
449
                       const gchar *mode,
450
                       GError     **error)
451
2.38k
{
452
2.38k
  int fid, flags;
453
2.38k
  mode_t create_mode;
454
2.38k
  GIOChannel *channel;
455
2.38k
  enum { /* Cheesy hack */
456
2.38k
    MODE_R = 1 << 0,
457
2.38k
    MODE_W = 1 << 1,
458
2.38k
    MODE_A = 1 << 2,
459
2.38k
    MODE_PLUS = 1 << 3,
460
2.38k
    MODE_R_PLUS = MODE_R | MODE_PLUS,
461
2.38k
    MODE_W_PLUS = MODE_W | MODE_PLUS,
462
2.38k
    MODE_A_PLUS = MODE_A | MODE_PLUS
463
2.38k
  } mode_num;
464
2.38k
  struct stat buffer;
465
466
2.38k
  g_return_val_if_fail (filename != NULL, NULL);
467
2.38k
  g_return_val_if_fail (mode != NULL, NULL);
468
2.38k
  g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
469
470
2.38k
  switch (mode[0])
471
2.38k
    {
472
2.38k
      case 'r':
473
2.38k
        mode_num = MODE_R;
474
2.38k
        break;
475
0
      case 'w':
476
0
        mode_num = MODE_W;
477
0
        break;
478
0
      case 'a':
479
0
        mode_num = MODE_A;
480
0
        break;
481
0
      default:
482
0
        g_warning ("Invalid GIOFileMode %s.", mode);
483
0
        return NULL;
484
2.38k
    }
485
486
2.38k
  switch (mode[1])
487
2.38k
    {
488
2.38k
      case '\0':
489
2.38k
        break;
490
0
      case '+':
491
0
        if (mode[2] == '\0')
492
0
          {
493
0
            mode_num |= MODE_PLUS;
494
0
            break;
495
0
          }
496
0
        G_GNUC_FALLTHROUGH;
497
0
      default:
498
0
        g_warning ("Invalid GIOFileMode %s.", mode);
499
0
        return NULL;
500
2.38k
    }
501
502
2.38k
  switch (mode_num)
503
2.38k
    {
504
2.38k
      case MODE_R:
505
2.38k
        flags = O_RDONLY;
506
2.38k
        break;
507
0
      case MODE_W:
508
0
        flags = O_WRONLY | O_TRUNC | O_CREAT;
509
0
        break;
510
0
      case MODE_A:
511
0
        flags = O_WRONLY | O_APPEND | O_CREAT;
512
0
        break;
513
0
      case MODE_R_PLUS:
514
0
        flags = O_RDWR;
515
0
        break;
516
0
      case MODE_W_PLUS:
517
0
        flags = O_RDWR | O_TRUNC | O_CREAT;
518
0
        break;
519
0
      case MODE_A_PLUS:
520
0
        flags = O_RDWR | O_APPEND | O_CREAT;
521
0
        break;
522
0
      case MODE_PLUS:
523
0
      default:
524
0
        g_assert_not_reached ();
525
0
        flags = 0;
526
2.38k
    }
527
528
2.38k
  create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
529
530
2.38k
  fid = g_open (filename, flags, create_mode);
531
2.38k
  if (fid == -1)
532
0
    {
533
0
      int err = errno;
534
0
      g_set_error_literal (error, G_FILE_ERROR,
535
0
                           g_file_error_from_errno (err),
536
0
                           g_strerror (err));
537
0
      return (GIOChannel *)NULL;
538
0
    }
539
540
2.38k
  if (fstat (fid, &buffer) == -1) /* In case someone opens a FIFO */
541
0
    {
542
0
      int err = errno;
543
0
      close (fid);
544
0
      g_set_error_literal (error, G_FILE_ERROR,
545
0
                           g_file_error_from_errno (err),
546
0
                           g_strerror (err));
547
0
      return (GIOChannel *)NULL;
548
0
    }
549
550
2.38k
  channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
551
552
2.38k
  channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
553
2.38k
                         || S_ISBLK (buffer.st_mode);
554
555
2.38k
  switch (mode_num)
556
2.38k
    {
557
2.38k
      case MODE_R:
558
2.38k
        channel->is_readable = TRUE;
559
2.38k
        channel->is_writeable = FALSE;
560
2.38k
        break;
561
0
      case MODE_W:
562
0
      case MODE_A:
563
0
        channel->is_readable = FALSE;
564
0
        channel->is_writeable = TRUE;
565
0
        break;
566
0
      case MODE_R_PLUS:
567
0
      case MODE_W_PLUS:
568
0
      case MODE_A_PLUS:
569
0
        channel->is_readable = TRUE;
570
0
        channel->is_writeable = TRUE;
571
0
        break;
572
0
      case MODE_PLUS:
573
0
      default:
574
0
        g_assert_not_reached ();
575
2.38k
    }
576
577
2.38k
  g_io_channel_init (channel);
578
2.38k
  channel->close_on_unref = TRUE; /* must be after g_io_channel_init () */
579
2.38k
  channel->funcs = &unix_channel_funcs;
580
581
2.38k
  ((GIOUnixChannel *) channel)->fd = fid;
582
2.38k
  return channel;
583
2.38k
}
584
585
/**
586
 * g_io_channel_unix_new:
587
 * @fd: a file descriptor.
588
 *
589
 * Creates a new #GIOChannel given a file descriptor. On UNIX systems
590
 * this works for plain files, pipes, and sockets.
591
 *
592
 * The returned #GIOChannel has a reference count of 1.
593
 *
594
 * The default encoding for #GIOChannel is UTF-8. If your application
595
 * is reading output from a command using via pipe, you may need to set
596
 * the encoding to the encoding of the current locale (see
597
 * g_get_charset()) with the g_io_channel_set_encoding() function.
598
 * By default, the fd passed will not be closed when the final reference
599
 * to the #GIOChannel data structure is dropped.
600
 *
601
 * If you want to read raw binary data without interpretation, then
602
 * call the g_io_channel_set_encoding() function with %NULL for the
603
 * encoding argument.
604
 *
605
 * This function is available in GLib on Windows, too, but you should
606
 * avoid using it on Windows. The domain of file descriptors and
607
 * sockets overlap. There is no way for GLib to know which one you mean
608
 * in case the argument you pass to this function happens to be both a
609
 * valid file descriptor and socket. If that happens a warning is
610
 * issued, and GLib assumes that it is the file descriptor you mean.
611
 *
612
 * Returns: a new #GIOChannel.
613
 **/
614
GIOChannel *
615
g_io_channel_unix_new (gint fd)
616
40.0k
{
617
40.0k
  struct stat buffer;
618
40.0k
  GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
619
40.0k
  GIOChannel *channel = (GIOChannel *)unix_channel;
620
621
40.0k
  g_io_channel_init (channel);
622
40.0k
  channel->funcs = &unix_channel_funcs;
623
624
40.0k
  unix_channel->fd = fd;
625
626
  /* I'm not sure if fstat on a non-file (e.g., socket) works
627
   * it should be safe to say if it fails, the fd isn't seekable.
628
   */
629
  /* Newer UNIX versions support S_ISSOCK(), fstat() will probably
630
   * succeed in most cases.
631
   */
632
40.0k
  if (fstat (unix_channel->fd, &buffer) == 0)
633
40.0k
    channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
634
40.0k
                           || S_ISBLK (buffer.st_mode);
635
0
  else /* Assume not seekable */
636
0
    channel->is_seekable = FALSE;
637
638
40.0k
  g_io_unix_get_flags (channel); /* Sets is_readable, is_writeable */
639
640
40.0k
  return channel;
641
40.0k
}
642
643
/**
644
 * g_io_channel_unix_get_fd:
645
 * @channel: a #GIOChannel, created with g_io_channel_unix_new().
646
 *
647
 * Returns the file descriptor of the #GIOChannel.
648
 *
649
 * On Windows this function returns the file descriptor or socket of
650
 * the #GIOChannel.
651
 *
652
 * Returns: the file descriptor of the #GIOChannel.
653
 **/
654
gint
655
g_io_channel_unix_get_fd (GIOChannel *channel)
656
39.2k
{
657
39.2k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
658
39.2k
  return unix_channel->fd;
659
39.2k
}