Update contrib.
     1 /* GLIB - Library of useful routines for C programming
 
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 
     4  * giounix.c: IO Channels using unix file descriptors
 
     5  * Copyright 1998 Owen Taylor
 
     6  * Portions copyright (c) 2006-2009 Nokia Corporation.  All rights reserved.
 
     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.
 
    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.
 
    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.
 
    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/. 
 
    37 #define _POSIX_SOURCE		/* for SSIZE_MAX */
 
    40 #include <sys/types.h>
 
    53 #endif /* __SYMBIAN32__ */
 
    59 typedef struct _GIOUnixChannel GIOUnixChannel;
 
    60 typedef struct _GIOUnixWatch GIOUnixWatch;
 
    62 struct _GIOUnixChannel
 
    73   GIOCondition  condition;
 
    77 static GIOStatus	g_io_unix_read		(GIOChannel   *channel,
 
    82 static GIOStatus	g_io_unix_write		(GIOChannel   *channel,
 
    87 static GIOStatus	g_io_unix_seek		(GIOChannel   *channel,
 
    91 static GIOStatus	g_io_unix_close		(GIOChannel   *channel,
 
    93 static void		g_io_unix_free		(GIOChannel   *channel);
 
    94 static GSource*		g_io_unix_create_watch	(GIOChannel   *channel,
 
    95 						 GIOCondition  condition);
 
    96 static GIOStatus	g_io_unix_set_flags	(GIOChannel   *channel,
 
    99 static GIOFlags 	g_io_unix_get_flags	(GIOChannel   *channel);
 
   101 static gboolean g_io_unix_prepare  (GSource     *source,
 
   103 static gboolean g_io_unix_check    (GSource     *source);
 
   104 static gboolean g_io_unix_dispatch (GSource     *source,
 
   105 				    GSourceFunc  callback,
 
   107 static void     g_io_unix_finalize (GSource     *source);
 
   111 PLS(g_io_watch_funcs,giounix,GSourceFuncs)
 
   112 #define g_io_watch_funcs  (*FUNCTION_NAME(g_io_watch_funcs,giounix)())
 
   114 const GSourceFuncs temp_g_io_watch_funcs = {
 
   124 GSourceFuncs g_io_watch_funcs = {
 
   131 #endif /* EMULATOR */
 
   134 EXPORT_C GSourceFuncs *_g_io_watch_funcs()
 
   136 	return &g_io_watch_funcs;
 
   138 #endif /* __SYMBIAN32__ */
 
   142 PLS(unix_channel_funcs,giounix,GIOFuncs )
 
   143 #define unix_channel_funcs (*FUNCTION_NAME(unix_channel_funcs,giounix)())
 
   145 const GIOFuncs temp_unix_channel_funcs = {
 
   150   g_io_unix_create_watch,
 
   159 static GIOFuncs unix_channel_funcs = {
 
   164   g_io_unix_create_watch,
 
   170 #endif /* EMULATOR */
 
   173 g_io_unix_prepare (GSource  *source,
 
   176   GIOUnixWatch *watch = (GIOUnixWatch *)source;
 
   177   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
 
   181   /* Only return TRUE here if _all_ bits in watch->condition will be set
 
   183   return ((watch->condition & buffer_condition) == watch->condition);
 
   187 g_io_unix_check (GSource  *source)
 
   189   GIOUnixWatch *watch = (GIOUnixWatch *)source;
 
   190   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
 
   191   GIOCondition poll_condition = watch->pollfd.revents;
 
   193   return ((poll_condition | buffer_condition) & watch->condition);
 
   197 g_io_unix_dispatch (GSource     *source,
 
   198 		    GSourceFunc  callback,
 
   202   GIOFunc func = (GIOFunc)callback;
 
   203   GIOUnixWatch *watch = (GIOUnixWatch *)source;
 
   204   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
 
   208       g_warning ("IO watch dispatched without callback\n"
 
   209 		 "You must call g_source_connect().");
 
   213   return (*func) (watch->channel,
 
   214 		  (watch->pollfd.revents | buffer_condition) & watch->condition,
 
   219 g_io_unix_finalize (GSource *source)
 
   221   GIOUnixWatch *watch = (GIOUnixWatch *)source;
 
   223   g_io_channel_unref (watch->channel);
 
   227 g_io_unix_read (GIOChannel *channel, 
 
   233   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   236   if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
 
   240   result = read (unix_channel->fd, buf, count);
 
   255             return G_IO_STATUS_AGAIN;
 
   258             g_set_error_literal (err, G_IO_CHANNEL_ERROR,
 
   259                                  g_io_channel_error_from_errno (errsv),
 
   261             return G_IO_STATUS_ERROR;
 
   265   *bytes_read = result;
 
   267   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
 
   271 g_io_unix_write (GIOChannel  *channel, 
 
   274 		 gsize      *bytes_written,
 
   277   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   281   result = write (unix_channel->fd, buf, count);
 
   296             return G_IO_STATUS_AGAIN;
 
   299             g_set_error_literal (err, G_IO_CHANNEL_ERROR,
 
   300                                  g_io_channel_error_from_errno (errsv),
 
   302             return G_IO_STATUS_ERROR;
 
   306   *bytes_written = result;
 
   308   return G_IO_STATUS_NORMAL;
 
   312 g_io_unix_seek (GIOChannel *channel,
 
   317   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   334       whence = -1; /* Shut the compiler up */
 
   335       g_assert_not_reached ();
 
   339   if (tmp_offset != offset)
 
   341       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
 
   342                            g_io_channel_error_from_errno (EINVAL),
 
   343                            g_strerror (EINVAL));
 
   344       return G_IO_STATUS_ERROR;
 
   347   result = lseek (unix_channel->fd, tmp_offset, whence);
 
   352       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
 
   353                            g_io_channel_error_from_errno (errsv),
 
   355       return G_IO_STATUS_ERROR;
 
   358   return G_IO_STATUS_NORMAL;
 
   363 g_io_unix_close (GIOChannel *channel,
 
   366   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   368   if (close (unix_channel->fd) < 0)
 
   371       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
 
   372                            g_io_channel_error_from_errno (errsv),
 
   374       return G_IO_STATUS_ERROR;
 
   377   return G_IO_STATUS_NORMAL;
 
   381 g_io_unix_free (GIOChannel *channel)
 
   383   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   385   g_free (unix_channel);
 
   389 g_io_unix_create_watch (GIOChannel   *channel,
 
   390 			GIOCondition  condition)
 
   392   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   397   source = g_source_new (&g_io_watch_funcs, sizeof (GIOUnixWatch));
 
   398   watch = (GIOUnixWatch *)source;
 
   400   watch->channel = channel;
 
   401   g_io_channel_ref (channel);
 
   403   watch->condition = condition;
 
   405   watch->pollfd.fd = unix_channel->fd;
 
   406   watch->pollfd.events = condition;
 
   408   g_source_add_poll (source, &watch->pollfd);
 
   414 g_io_unix_set_flags (GIOChannel *channel,
 
   419   GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
 
   423   if (flags & G_IO_FLAG_APPEND)
 
   424     fcntl_flags |= O_APPEND;
 
   425   if (flags & G_IO_FLAG_NONBLOCK)
 
   427     fcntl_flags |= O_NONBLOCK;
 
   429     fcntl_flags |= O_NDELAY;
 
   432   if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
 
   435       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
 
   436                            g_io_channel_error_from_errno (errsv),
 
   438       return G_IO_STATUS_ERROR;
 
   441   return G_IO_STATUS_NORMAL;
 
   445 g_io_unix_get_flags (GIOChannel *channel)
 
   449   GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
 
   451   fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
 
   453   if (fcntl_flags == -1)
 
   456       g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)\n",
 
   457 		 g_strerror (err), err);
 
   461   if (fcntl_flags & O_APPEND)
 
   462     flags |= G_IO_FLAG_APPEND;
 
   464   if (fcntl_flags & O_NONBLOCK)
 
   466   if (fcntl_flags & O_NDELAY)
 
   468     flags |= G_IO_FLAG_NONBLOCK;
 
   470   switch (fcntl_flags & (O_RDONLY | O_WRONLY | O_RDWR))
 
   473         channel->is_readable = TRUE;
 
   474         channel->is_writeable = FALSE;
 
   477         channel->is_readable = FALSE;
 
   478         channel->is_writeable = TRUE;
 
   481         channel->is_readable = TRUE;
 
   482         channel->is_writeable = TRUE;
 
   485         g_assert_not_reached ();
 
   491 EXPORT_C GIOChannel *
 
   492 g_io_channel_new_file (const gchar *filename,
 
   499   enum { /* Cheesy hack */
 
   507   g_return_val_if_fail (filename != NULL, NULL);
 
   508   g_return_val_if_fail (mode != NULL, NULL);
 
   509   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
 
   523         g_warning ("Invalid GIOFileMode %s.\n", mode);
 
   534             mode_num |= MODE_PLUS;
 
   539         g_warning ("Invalid GIOFileMode %s.\n", mode);
 
   549         flags = O_WRONLY | O_TRUNC | O_CREAT;
 
   552         flags = O_WRONLY | O_APPEND | O_CREAT;
 
   554       case MODE_R | MODE_PLUS:
 
   557       case MODE_W | MODE_PLUS:
 
   558         flags = O_RDWR | O_TRUNC | O_CREAT;
 
   560       case MODE_A | MODE_PLUS:
 
   561         flags = O_RDWR | O_APPEND | O_CREAT;
 
   564         g_assert_not_reached ();
 
   568   create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
 
   569   fid = open (filename, flags, create_mode);
 
   573       g_set_error_literal (error, G_FILE_ERROR,
 
   574                            g_file_error_from_errno (err),
 
   576       return (GIOChannel *)NULL;
 
   579   if (fstat (fid, &buffer) == -1) /* In case someone opens a FIFO */
 
   583       g_set_error_literal (error, G_FILE_ERROR,
 
   584                            g_file_error_from_errno (err),
 
   586       return (GIOChannel *)NULL;
 
   589   channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
 
   591   channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
 
   592                          || S_ISBLK (buffer.st_mode);
 
   597         channel->is_readable = TRUE;
 
   598         channel->is_writeable = FALSE;
 
   602         channel->is_readable = FALSE;
 
   603         channel->is_writeable = TRUE;
 
   605       case MODE_R | MODE_PLUS:
 
   606       case MODE_W | MODE_PLUS:
 
   607       case MODE_A | MODE_PLUS:
 
   608         channel->is_readable = TRUE;
 
   609         channel->is_writeable = TRUE;
 
   612         g_assert_not_reached ();
 
   615   g_io_channel_init (channel);
 
   616   channel->close_on_unref = TRUE; /* must be after g_io_channel_init () */
 
   617   channel->funcs = &unix_channel_funcs;
 
   619   ((GIOUnixChannel *) channel)->fd = fid;
 
   623 EXPORT_C GIOChannel *
 
   624 g_io_channel_unix_new (gint fd)
 
   627   GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
 
   628   GIOChannel *channel = (GIOChannel *)unix_channel;
 
   630   g_io_channel_init (channel);
 
   631   channel->funcs = &unix_channel_funcs;
 
   633   unix_channel->fd = fd;
 
   635   /* I'm not sure if fstat on a non-file (e.g., socket) works
 
   636    * it should be safe to say if it fails, the fd isn't seekable.
 
   638   /* Newer UNIX versions support S_ISSOCK(), fstat() will probably
 
   639    * succeed in most cases.
 
   641   if (fstat (unix_channel->fd, &buffer) == 0)
 
   642     channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
 
   643                            || S_ISBLK (buffer.st_mode);
 
   644   else /* Assume not seekable */
 
   645     channel->is_seekable = FALSE;
 
   647   g_io_unix_get_flags (channel); /* Sets is_readable, is_writeable */
 
   653 g_io_channel_unix_get_fd (GIOChannel *channel)
 
   655   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
 
   656   return unix_channel->fd;
 
   659 #define __G_IO_UNIX_C__
 
   660 #include "galiasdef.c"