source: trunk/third/glib/giounix.c @ 14479

Revision 14479, 6.9 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14478, which included commits to RCS files with non-trunk default branches.
Line 
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 Library 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 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library 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-1999.  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 "glib.h"
35#include <sys/types.h>
36#include <unistd.h>
37#include <errno.h>
38
39/*
40 * Unix IO Channels
41 */
42
43typedef struct _GIOUnixChannel GIOUnixChannel;
44typedef struct _GIOUnixWatch GIOUnixWatch;
45
46struct _GIOUnixChannel {
47  GIOChannel channel;
48  gint fd;
49};
50
51struct _GIOUnixWatch {
52  GPollFD       pollfd;
53  GIOChannel   *channel;
54  GIOCondition  condition;
55  GIOFunc       callback;
56};
57
58
59static GIOError g_io_unix_read (GIOChannel *channel,
60                       gchar     *buf,
61                       guint      count,
62                       guint     *bytes_written);
63                       
64static GIOError g_io_unix_write(GIOChannel *channel,
65                                gchar     *buf,
66                                guint      count,
67                                guint     *bytes_written);
68static GIOError g_io_unix_seek (GIOChannel *channel,
69                                gint      offset,
70                                GSeekType type);
71static void g_io_unix_close    (GIOChannel *channel);
72static void g_io_unix_free     (GIOChannel *channel);
73static guint  g_io_unix_add_watch (GIOChannel      *channel,
74                                   gint           priority,
75                                   GIOCondition   condition,
76                                   GIOFunc        func,
77                                   gpointer       user_data,
78                                   GDestroyNotify notify);
79static gboolean g_io_unix_prepare  (gpointer source_data,
80                                    GTimeVal *current_time,
81                                    gint *timeout,
82                                    gpointer user_data);
83static gboolean g_io_unix_check    (gpointer source_data,
84                                    GTimeVal *current_time,
85                                    gpointer user_data);
86static gboolean g_io_unix_dispatch (gpointer source_data,
87                                    GTimeVal *current_time,
88                                    gpointer user_data);
89static void g_io_unix_destroy  (gpointer source_data);
90
91GSourceFuncs unix_watch_funcs = {
92  g_io_unix_prepare,
93  g_io_unix_check,
94  g_io_unix_dispatch,
95  g_io_unix_destroy
96};
97
98GIOFuncs unix_channel_funcs = {
99  g_io_unix_read,
100  g_io_unix_write,
101  g_io_unix_seek,
102  g_io_unix_close,
103  g_io_unix_add_watch,
104  g_io_unix_free,
105};
106
107static gboolean
108g_io_unix_prepare  (gpointer source_data,
109                    GTimeVal *current_time,
110                    gint     *timeout,
111                    gpointer user_data)
112{
113  *timeout = -1;
114  return FALSE;
115}
116
117static gboolean
118g_io_unix_check    (gpointer source_data,
119                    GTimeVal *current_time,
120                    gpointer user_data)
121{
122  GIOUnixWatch *data = source_data;
123
124  return (data->pollfd.revents & data->condition);
125}
126
127static gboolean
128g_io_unix_dispatch (gpointer source_data,
129                    GTimeVal *current_time,
130                    gpointer user_data)
131
132{
133  GIOUnixWatch *data = source_data;
134
135  return (*data->callback)(data->channel,
136                           data->pollfd.revents & data->condition,
137                           user_data);
138}
139
140static void
141g_io_unix_destroy (gpointer source_data)
142{
143  GIOUnixWatch *data = source_data;
144
145  g_main_remove_poll (&data->pollfd);
146  g_io_channel_unref (data->channel);
147  g_free (data);
148}
149
150static GIOError
151g_io_unix_read (GIOChannel *channel,
152                gchar     *buf,
153                guint      count,
154                guint     *bytes_read)
155{
156  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
157  gint result;
158
159  result = read (unix_channel->fd, buf, count);
160
161  if (result < 0)
162    {
163      *bytes_read = 0;
164      switch (errno)
165        {
166        case EINVAL:
167          return G_IO_ERROR_INVAL;
168        case EAGAIN:
169          return G_IO_ERROR_AGAIN;
170        default:
171          return G_IO_ERROR_UNKNOWN;
172        }
173    }
174  else
175    {
176      *bytes_read = result;
177      return G_IO_ERROR_NONE;
178    }
179}
180                       
181static GIOError
182g_io_unix_write(GIOChannel *channel,
183                gchar     *buf,
184                guint      count,
185                guint     *bytes_written)
186{
187  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
188  gint result;
189
190  result = write (unix_channel->fd, buf, count);
191
192  if (result < 0)
193    {
194      *bytes_written = 0;
195      switch (errno)
196        {
197        case EINVAL:
198          return G_IO_ERROR_INVAL;
199        case EAGAIN:
200          return G_IO_ERROR_AGAIN;
201        default:
202          return G_IO_ERROR_UNKNOWN;
203        }
204    }
205  else
206    {
207      *bytes_written = result;
208      return G_IO_ERROR_NONE;
209    }
210}
211
212static GIOError
213g_io_unix_seek (GIOChannel *channel,
214                gint      offset,
215                GSeekType type)
216{
217  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
218  int whence;
219  off_t result;
220
221  switch (type)
222    {
223    case G_SEEK_SET:
224      whence = SEEK_SET;
225      break;
226    case G_SEEK_CUR:
227      whence = SEEK_CUR;
228      break;
229    case G_SEEK_END:
230      whence = SEEK_END;
231      break;
232    default:
233      g_warning ("g_io_unix_seek: unknown seek type");
234      return G_IO_ERROR_UNKNOWN;
235    }
236
237  result = lseek (unix_channel->fd, offset, whence);
238
239  if (result < 0)
240    {
241      switch (errno)
242        {
243        case EINVAL:
244          return G_IO_ERROR_INVAL;
245        default:
246          return G_IO_ERROR_UNKNOWN;
247        }
248    }
249  else
250    return G_IO_ERROR_NONE;
251}
252
253
254static void
255g_io_unix_close (GIOChannel *channel)
256{
257  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
258
259  close (unix_channel->fd);
260}
261
262static void
263g_io_unix_free (GIOChannel *channel)
264{
265  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
266
267  g_free (unix_channel);
268}
269
270static guint
271g_io_unix_add_watch (GIOChannel    *channel,
272                     gint           priority,
273                     GIOCondition   condition,
274                     GIOFunc        func,
275                     gpointer       user_data,
276                     GDestroyNotify notify)
277{
278  GIOUnixWatch *watch = g_new (GIOUnixWatch, 1);
279  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
280 
281  watch->channel = channel;
282  g_io_channel_ref (channel);
283
284  watch->callback = func;
285  watch->condition = condition;
286
287  watch->pollfd.fd = unix_channel->fd;
288  watch->pollfd.events = condition;
289
290  g_main_add_poll (&watch->pollfd, priority);
291
292  return g_source_add (priority, TRUE, &unix_watch_funcs, watch, user_data, notify);
293}
294
295GIOChannel *
296g_io_channel_unix_new (gint fd)
297{
298  GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
299  GIOChannel *channel = (GIOChannel *)unix_channel;
300
301  g_io_channel_init (channel);
302  channel->funcs = &unix_channel_funcs;
303
304  unix_channel->fd = fd;
305  return channel;
306}
307
308gint
309g_io_channel_unix_get_fd (GIOChannel *channel)
310{
311  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
312  return unix_channel->fd;
313}
Note: See TracBrowser for help on using the repository browser.