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