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