Main Page | Class List | Directories | File List | Class Members | File Members

giounix.c

Go to the documentation of this file.
00001 /* GLIB - Library of useful routines for C programming
00002  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * giounix.c: IO Channels using unix file descriptors
00005  * Copyright 1998 Owen Taylor
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Library General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public
00018  * License along with this library; if not, write to the
00019  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  * Boston, MA 02111-1307, USA.
00021  */
00022 
00023 /*
00024  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
00025  * file for a list of people on the GLib Team.  See the ChangeLog
00026  * files for a list of changes.  These files are distributed with
00027  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
00028  */
00029 
00030 /* 
00031  * MT safe
00032  */
00033 
00034 #include "glib.h"
00035 #include <sys/types.h>
00036 #include <unistd.h>
00037 #include <errno.h>
00038 
00039 /*
00040  * Unix IO Channels
00041  */
00042 
00043 typedef struct _GIOUnixChannel GIOUnixChannel;
00044 typedef struct _GIOUnixWatch GIOUnixWatch;
00045 
00046 struct _GIOUnixChannel {
00047   GIOChannel channel;
00048   gint fd;
00049 };
00050 
00051 struct _GIOUnixWatch {
00052   GPollFD       pollfd;
00053   GIOChannel   *channel;
00054   GIOCondition  condition;
00055   GIOFunc       callback;
00056 };
00057 
00058 
00059 static GIOError g_io_unix_read (GIOChannel *channel, 
00060                        gchar     *buf, 
00061                        guint      count,
00062                        guint     *bytes_written);
00063                        
00064 static GIOError g_io_unix_write(GIOChannel *channel, 
00065                                 gchar     *buf, 
00066                                 guint      count,
00067                                 guint     *bytes_written);
00068 static GIOError g_io_unix_seek (GIOChannel *channel,
00069                                 gint      offset, 
00070                                 GSeekType type);
00071 static void g_io_unix_close    (GIOChannel *channel);
00072 static void g_io_unix_free     (GIOChannel *channel);
00073 static guint  g_io_unix_add_watch (GIOChannel      *channel,
00074                                    gint           priority,
00075                                    GIOCondition   condition,
00076                                    GIOFunc        func,
00077                                    gpointer       user_data,
00078                                    GDestroyNotify notify);
00079 static gboolean g_io_unix_prepare  (gpointer source_data, 
00080                                     GTimeVal *current_time,
00081                                     gint *timeout,
00082                                     gpointer user_data);
00083 static gboolean g_io_unix_check    (gpointer source_data,
00084                                     GTimeVal *current_time,
00085                                     gpointer user_data);
00086 static gboolean g_io_unix_dispatch (gpointer source_data,
00087                                     GTimeVal *current_time,
00088                                     gpointer user_data);
00089 static void g_io_unix_destroy  (gpointer source_data);
00090 
00091 GSourceFuncs unix_watch_funcs = {
00092   g_io_unix_prepare,
00093   g_io_unix_check,
00094   g_io_unix_dispatch,
00095   g_io_unix_destroy
00096 };
00097 
00098 GIOFuncs unix_channel_funcs = {
00099   g_io_unix_read,
00100   g_io_unix_write,
00101   g_io_unix_seek,
00102   g_io_unix_close,
00103   g_io_unix_add_watch,
00104   g_io_unix_free,
00105 };
00106 
00107 static gboolean 
00108 g_io_unix_prepare  (gpointer source_data, 
00109                     GTimeVal *current_time,
00110                     gint     *timeout,
00111                     gpointer user_data)
00112 {
00113   *timeout = -1;
00114   return FALSE;
00115 }
00116 
00117 static gboolean 
00118 g_io_unix_check    (gpointer source_data,
00119                     GTimeVal *current_time,
00120                     gpointer user_data)
00121 {
00122   GIOUnixWatch *data = source_data;
00123 
00124   return (data->pollfd.revents & data->condition);
00125 }
00126 
00127 static gboolean
00128 g_io_unix_dispatch (gpointer source_data, 
00129                     GTimeVal *current_time,
00130                     gpointer user_data)
00131 
00132 {
00133   GIOUnixWatch *data = source_data;
00134 
00135   return (*data->callback)(data->channel,
00136                            data->pollfd.revents & data->condition,
00137                            user_data);
00138 }
00139 
00140 static void 
00141 g_io_unix_destroy (gpointer source_data)
00142 {
00143   GIOUnixWatch *data = source_data;
00144 
00145   g_main_remove_poll (&data->pollfd);
00146   g_io_channel_unref (data->channel);
00147   g_free (data);
00148 }
00149 
00150 static GIOError 
00151 g_io_unix_read (GIOChannel *channel, 
00152                 gchar     *buf, 
00153                 guint      count,
00154                 guint     *bytes_read)
00155 {
00156   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00157   gint result;
00158 
00159   result = read (unix_channel->fd, buf, count);
00160 
00161   if (result < 0)
00162     {
00163       *bytes_read = 0;
00164       switch (errno)
00165         {
00166         case EINVAL:
00167           return G_IO_ERROR_INVAL;
00168         case EAGAIN:
00169           return G_IO_ERROR_AGAIN;
00170         default:
00171           return G_IO_ERROR_UNKNOWN;
00172         }
00173     }
00174   else
00175     {
00176       *bytes_read = result;
00177       return G_IO_ERROR_NONE;
00178     }
00179 }
00180                        
00181 static GIOError 
00182 g_io_unix_write(GIOChannel *channel, 
00183                 gchar     *buf, 
00184                 guint      count,
00185                 guint     *bytes_written)
00186 {
00187   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00188   gint result;
00189 
00190   result = write (unix_channel->fd, buf, count);
00191 
00192   if (result < 0)
00193     {
00194       *bytes_written = 0;
00195       switch (errno)
00196         {
00197         case EINVAL:
00198           return G_IO_ERROR_INVAL;
00199         case EAGAIN:
00200           return G_IO_ERROR_AGAIN;
00201         default:
00202           return G_IO_ERROR_UNKNOWN;
00203         }
00204     }
00205   else
00206     {
00207       *bytes_written = result;
00208       return G_IO_ERROR_NONE;
00209     }
00210 }
00211 
00212 static GIOError 
00213 g_io_unix_seek (GIOChannel *channel,
00214                 gint      offset, 
00215                 GSeekType type)
00216 {
00217   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00218   int whence;
00219   off_t result;
00220 
00221   switch (type)
00222     {
00223     case G_SEEK_SET:
00224       whence = SEEK_SET;
00225       break;
00226     case G_SEEK_CUR:
00227       whence = SEEK_CUR;
00228       break;
00229     case G_SEEK_END:
00230       whence = SEEK_END;
00231       break;
00232     default:
00233       g_warning ("g_io_unix_seek: unknown seek type");
00234       return G_IO_ERROR_UNKNOWN;
00235     }
00236 
00237   result = lseek (unix_channel->fd, offset, whence);
00238 
00239   if (result < 0)
00240     {
00241       switch (errno)
00242         {
00243         case EINVAL:
00244           return G_IO_ERROR_INVAL;
00245         default:
00246           return G_IO_ERROR_UNKNOWN;
00247         }
00248     }
00249   else
00250     return G_IO_ERROR_NONE;
00251 }
00252 
00253 
00254 static void 
00255 g_io_unix_close (GIOChannel *channel)
00256 {
00257   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00258 
00259   close (unix_channel->fd);
00260 }
00261 
00262 static void 
00263 g_io_unix_free (GIOChannel *channel)
00264 {
00265   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00266 
00267   g_free (unix_channel);
00268 }
00269 
00270 static guint 
00271 g_io_unix_add_watch (GIOChannel    *channel,
00272                      gint           priority,
00273                      GIOCondition   condition,
00274                      GIOFunc        func,
00275                      gpointer       user_data,
00276                      GDestroyNotify notify)
00277 {
00278   GIOUnixWatch *watch = g_new (GIOUnixWatch, 1);
00279   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00280   
00281   watch->channel = channel;
00282   g_io_channel_ref (channel);
00283 
00284   watch->callback = func;
00285   watch->condition = condition;
00286 
00287   watch->pollfd.fd = unix_channel->fd;
00288   watch->pollfd.events = condition;
00289 
00290   g_main_add_poll (&watch->pollfd, priority);
00291 
00292   return g_source_add (priority, TRUE, &unix_watch_funcs, watch, user_data, notify);
00293 }
00294 
00295 GIOChannel *
00296 g_io_channel_unix_new (gint fd)
00297 {
00298   GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
00299   GIOChannel *channel = (GIOChannel *)unix_channel;
00300 
00301   g_io_channel_init (channel);
00302   channel->funcs = &unix_channel_funcs;
00303 
00304   unix_channel->fd = fd;
00305   return channel;
00306 }
00307 
00308 gint
00309 g_io_channel_unix_get_fd (GIOChannel *channel)
00310 {
00311   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
00312   return unix_channel->fd;
00313 }

© sourcejam.com 2005-2008