00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "glib.h"
00035 #include <sys/types.h>
00036 #include <unistd.h>
00037 #include <errno.h>
00038
00039
00040
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 }