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