Coverage Report

Created: 2025-12-14 06:30

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
48.0k
{
188
48.0k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
189
48.0k
  gssize result;
190
191
48.0k
  if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
192
0
    count = SSIZE_MAX;
193
194
48.0k
 retry:
195
48.0k
  result = read (unix_channel->fd, buf, count);
196
197
48.0k
  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
48.0k
  *bytes_read = result;
221
222
48.0k
  return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
223
48.0k
}
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.91k
{
232
9.91k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
233
9.91k
  gssize result;
234
235
9.91k
 retry:
236
9.91k
  result = write (unix_channel->fd, buf, count);
237
238
9.91k
  if (result < 0)
239
7.88k
    {
240
7.88k
      int errsv = errno;
241
7.88k
      *bytes_written = 0;
242
243
7.88k
      switch (errsv)
244
7.88k
        {
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.88k
          default:
254
7.88k
            g_set_error_literal (err, G_IO_CHANNEL_ERROR,
255
7.88k
                                 g_io_channel_error_from_errno (errsv),
256
7.88k
                                 g_strerror (errsv));
257
7.88k
            return G_IO_STATUS_ERROR;
258
7.88k
        }
259
7.88k
    }
260
261
2.02k
  *bytes_written = result;
262
263
2.02k
  return G_IO_STATUS_NORMAL;
264
9.91k
}
265
266
static GIOStatus
267
g_io_unix_seek (GIOChannel *channel,
268
    gint64      offset, 
269
    GSeekType   type,
270
                GError    **err)
271
3.32k
{
272
3.32k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
273
3.32k
  int whence;
274
3.32k
  off_t tmp_offset;
275
3.32k
  off_t result;
276
277
3.32k
  switch (type)
278
3.32k
    {
279
3.32k
    case G_SEEK_SET:
280
3.32k
      whence = SEEK_SET;
281
3.32k
      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
3.32k
    }
292
293
3.32k
  tmp_offset = offset;
294
3.32k
  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
3.32k
  result = lseek (unix_channel->fd, tmp_offset, whence);
303
304
3.32k
  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
3.32k
  return G_IO_STATUS_NORMAL;
314
3.32k
}
315
316
317
static GIOStatus
318
g_io_unix_close (GIOChannel *channel,
319
     GError    **err)
320
75.3k
{
321
75.3k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
322
323
75.3k
  if (close (unix_channel->fd) < 0)
324
35.8k
    {
325
35.8k
      int errsv = errno;
326
35.8k
      g_set_error_literal (err, G_IO_CHANNEL_ERROR,
327
35.8k
                           g_io_channel_error_from_errno (errsv),
328
35.8k
                           g_strerror (errsv));
329
35.8k
      return G_IO_STATUS_ERROR;
330
35.8k
    }
331
332
39.5k
  return G_IO_STATUS_NORMAL;
333
75.3k
}
334
335
static void 
336
g_io_unix_free (GIOChannel *channel)
337
39.5k
{
338
39.5k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
339
340
39.5k
  g_free (unix_channel);
341
39.5k
}
342
343
static GSource *
344
g_io_unix_create_watch (GIOChannel   *channel,
345
      GIOCondition  condition)
346
454
{
347
454
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
348
454
  GSource *source;
349
454
  GIOUnixWatch *watch;
350
351
352
454
  source = g_source_new (&g_io_watch_funcs, sizeof (GIOUnixWatch));
353
454
  g_source_set_static_name (source, "GIOChannel (Unix)");
354
454
  watch = (GIOUnixWatch *)source;
355
  
356
454
  watch->channel = channel;
357
454
  g_io_channel_ref (channel);
358
  
359
454
  watch->condition = condition;
360
361
454
  watch->pollfd.fd = unix_channel->fd;
362
454
  watch->pollfd.events = condition;
363
364
454
  g_source_add_poll (source, &watch->pollfd);
365
366
454
  return source;
367
454
}
368
369
static GIOStatus
370
g_io_unix_set_flags (GIOChannel *channel,
371
                     GIOFlags    flags,
372
                     GError    **err)
373
7.97k
{
374
7.97k
  glong fcntl_flags;
375
7.97k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
376
377
7.97k
  fcntl_flags = 0;
378
379
7.97k
  if (flags & G_IO_FLAG_APPEND)
380
0
    fcntl_flags |= O_APPEND;
381
7.97k
  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.97k
  if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
389
7.88k
    {
390
7.88k
      int errsv = errno;
391
7.88k
      g_set_error_literal (err, G_IO_CHANNEL_ERROR,
392
7.88k
                           g_io_channel_error_from_errno (errsv),
393
7.88k
                           g_strerror (errsv));
394
7.88k
      return G_IO_STATUS_ERROR;
395
7.88k
    }
396
397
92
  return G_IO_STATUS_NORMAL;
398
7.97k
}
399
400
static GIOFlags
401
g_io_unix_get_flags (GIOChannel *channel)
402
44.6k
{
403
44.6k
  GIOFlags flags = G_IO_FLAG_NONE;
404
44.6k
  glong fcntl_flags;
405
44.6k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
406
407
44.6k
  fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
408
409
44.6k
  if (fcntl_flags == -1)
410
7.88k
    {
411
7.88k
      int err = errno;
412
7.88k
      g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)",
413
7.88k
     g_strerror (err), err);
414
7.88k
      return 0;
415
7.88k
    }
416
417
36.7k
  if (fcntl_flags & O_APPEND)
418
0
    flags |= G_IO_FLAG_APPEND;
419
36.7k
#ifdef O_NONBLOCK
420
36.7k
  if (fcntl_flags & O_NONBLOCK)
421
#else
422
  if (fcntl_flags & O_NDELAY)
423
#endif
424
0
    flags |= G_IO_FLAG_NONBLOCK;
425
426
36.7k
  switch (fcntl_flags & (O_RDONLY | O_WRONLY | O_RDWR))
427
36.7k
    {
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
36.7k
      case O_RDWR:
437
36.7k
        channel->is_readable = TRUE;
438
36.7k
        channel->is_writeable = TRUE;
439
36.7k
        break;
440
0
      default:
441
0
        g_assert_not_reached ();
442
36.7k
    }
443
444
36.7k
  return flags;
445
36.7k
}
446
447
GIOChannel *
448
g_io_channel_new_file (const gchar *filename,
449
                       const gchar *mode,
450
                       GError     **error)
451
3.32k
{
452
3.32k
  int fid, flags;
453
3.32k
  mode_t create_mode;
454
3.32k
  GIOChannel *channel;
455
3.32k
  enum { /* Cheesy hack */
456
3.32k
    MODE_R = 1 << 0,
457
3.32k
    MODE_W = 1 << 1,
458
3.32k
    MODE_A = 1 << 2,
459
3.32k
    MODE_PLUS = 1 << 3,
460
3.32k
    MODE_R_PLUS = MODE_R | MODE_PLUS,
461
3.32k
    MODE_W_PLUS = MODE_W | MODE_PLUS,
462
3.32k
    MODE_A_PLUS = MODE_A | MODE_PLUS
463
3.32k
  } mode_num;
464
3.32k
  struct stat buffer;
465
466
3.32k
  g_return_val_if_fail (filename != NULL, NULL);
467
3.32k
  g_return_val_if_fail (mode != NULL, NULL);
468
3.32k
  g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
469
470
3.32k
  switch (mode[0])
471
3.32k
    {
472
3.32k
      case 'r':
473
3.32k
        mode_num = MODE_R;
474
3.32k
        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
3.32k
    }
485
486
3.32k
  switch (mode[1])
487
3.32k
    {
488
3.32k
      case '\0':
489
3.32k
        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
3.32k
    }
501
502
3.32k
  switch (mode_num)
503
3.32k
    {
504
3.32k
      case MODE_R:
505
3.32k
        flags = O_RDONLY;
506
3.32k
        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
3.32k
    }
527
528
3.32k
  create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
529
530
3.32k
  fid = g_open (filename, flags, create_mode);
531
3.32k
  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
3.32k
  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
3.32k
  channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
551
552
3.32k
  channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
553
3.32k
                         || S_ISBLK (buffer.st_mode);
554
555
3.32k
  switch (mode_num)
556
3.32k
    {
557
3.32k
      case MODE_R:
558
3.32k
        channel->is_readable = TRUE;
559
3.32k
        channel->is_writeable = FALSE;
560
3.32k
        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
3.32k
    }
576
577
3.32k
  g_io_channel_init (channel);
578
3.32k
  channel->close_on_unref = TRUE; /* must be after g_io_channel_init () */
579
3.32k
  channel->funcs = &unix_channel_funcs;
580
581
3.32k
  ((GIOUnixChannel *) channel)->fd = fid;
582
3.32k
  return channel;
583
3.32k
}
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
36.6k
{
617
36.6k
  struct stat buffer;
618
36.6k
  GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
619
36.6k
  GIOChannel *channel = (GIOChannel *)unix_channel;
620
621
36.6k
  g_io_channel_init (channel);
622
36.6k
  channel->funcs = &unix_channel_funcs;
623
624
36.6k
  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
36.6k
  if (fstat (unix_channel->fd, &buffer) == 0)
633
36.6k
    channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
634
36.6k
                           || S_ISBLK (buffer.st_mode);
635
0
  else /* Assume not seekable */
636
0
    channel->is_seekable = FALSE;
637
638
36.6k
  g_io_unix_get_flags (channel); /* Sets is_readable, is_writeable */
639
640
36.6k
  return channel;
641
36.6k
}
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
35.8k
{
657
35.8k
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
658
35.8k
  return unix_channel->fd;
659
35.8k
}