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