Don't define WIN32 and NATIVE_WIN32.
[platform/upstream/glib.git] / glib / 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 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
43 typedef struct _GIOUnixChannel GIOUnixChannel;
44 typedef struct _GIOUnixWatch GIOUnixWatch;
45
46 struct _GIOUnixChannel {
47   GIOChannel channel;
48   gint fd;
49 };
50
51 struct _GIOUnixWatch {
52   GPollFD       pollfd;
53   GIOChannel   *channel;
54   GIOCondition  condition;
55   GIOFunc       callback;
56 };
57
58
59 static GIOError g_io_unix_read (GIOChannel *channel, 
60                        gchar     *buf, 
61                        guint      count,
62                        guint     *bytes_written);
63                        
64 static GIOError g_io_unix_write(GIOChannel *channel, 
65                                 gchar     *buf, 
66                                 guint      count,
67                                 guint     *bytes_written);
68 static GIOError g_io_unix_seek (GIOChannel *channel,
69                                 gint      offset, 
70                                 GSeekType type);
71 static void g_io_unix_close    (GIOChannel *channel);
72 static void g_io_unix_free     (GIOChannel *channel);
73 static guint  g_io_unix_add_watch (GIOChannel      *channel,
74                                    gint           priority,
75                                    GIOCondition   condition,
76                                    GIOFunc        func,
77                                    gpointer       user_data,
78                                    GDestroyNotify notify);
79 static gboolean g_io_unix_prepare  (gpointer source_data, 
80                                     GTimeVal *current_time,
81                                     gint *timeout,
82                                     gpointer user_data);
83 static gboolean g_io_unix_check    (gpointer source_data,
84                                     GTimeVal *current_time,
85                                     gpointer user_data);
86 static gboolean g_io_unix_dispatch (gpointer source_data,
87                                     GTimeVal *current_time,
88                                     gpointer user_data);
89 static void g_io_unix_destroy  (gpointer source_data);
90
91 GSourceFuncs 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
98 GIOFuncs 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
107 static gboolean 
108 g_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
117 static gboolean 
118 g_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
127 static gboolean
128 g_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
140 static void 
141 g_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
150 static GIOError 
151 g_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                        
181 static GIOError 
182 g_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
212 static GIOError 
213 g_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
254 static void 
255 g_io_unix_close (GIOChannel *channel)
256 {
257   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
258
259   close (unix_channel->fd);
260 }
261
262 static void 
263 g_io_unix_free (GIOChannel *channel)
264 {
265   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
266
267   g_free (unix_channel);
268 }
269
270 static guint 
271 g_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
295 GIOChannel *
296 g_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
308 gint
309 g_io_channel_unix_get_fd (GIOChannel *channel)
310 {
311   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
312   return unix_channel->fd;
313 }