Correct rules for making the win32-related files that are made from
[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 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 static gboolean g_io_unix_check    (gpointer source_data,
83                                     GTimeVal *current_time);
84 static gboolean g_io_unix_dispatch (gpointer source_data,
85                                     GTimeVal *current_time,
86                                     gpointer user_data);
87 static void g_io_unix_destroy  (gpointer source_data);
88
89 GSourceFuncs unix_watch_funcs = {
90   g_io_unix_prepare,
91   g_io_unix_check,
92   g_io_unix_dispatch,
93   g_io_unix_destroy
94 };
95
96 GIOFuncs unix_channel_funcs = {
97   g_io_unix_read,
98   g_io_unix_write,
99   g_io_unix_seek,
100   g_io_unix_close,
101   g_io_unix_add_watch,
102   g_io_unix_free,
103 };
104
105 static gboolean 
106 g_io_unix_prepare  (gpointer source_data, 
107                     GTimeVal *current_time,
108                     gint    *timeout)
109 {
110   *timeout = -1;
111   return FALSE;
112 }
113
114 static gboolean 
115 g_io_unix_check    (gpointer source_data,
116                     GTimeVal *current_time)
117 {
118   GIOUnixWatch *data = source_data;
119
120   return (data->pollfd.revents & data->condition);
121 }
122
123 static gboolean
124 g_io_unix_dispatch (gpointer source_data, 
125                     GTimeVal *current_time,
126                     gpointer user_data)
127
128 {
129   GIOUnixWatch *data = source_data;
130
131   return (*data->callback)(data->channel,
132                            data->pollfd.revents & data->condition,
133                            user_data);
134 }
135
136 static void 
137 g_io_unix_destroy (gpointer source_data)
138 {
139   GIOUnixWatch *data = source_data;
140
141   g_main_remove_poll (&data->pollfd);
142   g_io_channel_unref (data->channel);
143   g_free (data);
144 }
145
146 static GIOError 
147 g_io_unix_read (GIOChannel *channel, 
148                 gchar     *buf, 
149                 guint      count,
150                 guint     *bytes_read)
151 {
152   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
153   gint result;
154
155   result = read (unix_channel->fd, buf, count);
156
157   if (result < 0)
158     {
159       *bytes_read = 0;
160       switch (errno)
161         {
162         case EINVAL:
163           return G_IO_ERROR_INVAL;
164         case EAGAIN:
165           return G_IO_ERROR_AGAIN;
166         default:
167           return G_IO_ERROR_UNKNOWN;
168         }
169     }
170   else
171     {
172       *bytes_read = result;
173       return G_IO_ERROR_NONE;
174     }
175 }
176                        
177 static GIOError 
178 g_io_unix_write(GIOChannel *channel, 
179                 gchar     *buf, 
180                 guint      count,
181                 guint     *bytes_written)
182 {
183   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
184   gint result;
185
186   result = write (unix_channel->fd, buf, count);
187
188   if (result < 0)
189     {
190       *bytes_written = 0;
191       switch (errno)
192         {
193         case EINVAL:
194           return G_IO_ERROR_INVAL;
195         case EAGAIN:
196           return G_IO_ERROR_AGAIN;
197         default:
198           return G_IO_ERROR_UNKNOWN;
199         }
200     }
201   else
202     {
203       *bytes_written = result;
204       return G_IO_ERROR_NONE;
205     }
206 }
207
208 static GIOError 
209 g_io_unix_seek (GIOChannel *channel,
210                 gint      offset, 
211                 GSeekType type)
212 {
213   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
214   int whence;
215   off_t result;
216
217   switch (type)
218     {
219     case G_SEEK_SET:
220       whence = SEEK_SET;
221       break;
222     case G_SEEK_CUR:
223       whence = SEEK_CUR;
224       break;
225     case G_SEEK_END:
226       whence = SEEK_END;
227       break;
228     default:
229       g_warning ("g_io_unix_seek: unknown seek type");
230       return G_IO_ERROR_UNKNOWN;
231     }
232
233   result = lseek (unix_channel->fd, offset, whence);
234
235   if (result < 0)
236     {
237       switch (errno)
238         {
239         case EINVAL:
240           return G_IO_ERROR_INVAL;
241         default:
242           return G_IO_ERROR_UNKNOWN;
243         }
244     }
245   else
246     return G_IO_ERROR_NONE;
247 }
248
249
250 static void 
251 g_io_unix_close (GIOChannel *channel)
252 {
253   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
254
255   close (unix_channel->fd);
256 }
257
258 static void 
259 g_io_unix_free (GIOChannel *channel)
260 {
261   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
262
263   g_free (unix_channel);
264 }
265
266 static guint 
267 g_io_unix_add_watch (GIOChannel    *channel,
268                      gint           priority,
269                      GIOCondition   condition,
270                      GIOFunc        func,
271                      gpointer       user_data,
272                      GDestroyNotify notify)
273 {
274   GIOUnixWatch *watch = g_new (GIOUnixWatch, 1);
275   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
276   
277   watch->channel = channel;
278   g_io_channel_ref (channel);
279
280   watch->callback = func;
281   watch->condition = condition;
282
283   watch->pollfd.fd = unix_channel->fd;
284   watch->pollfd.events = condition;
285
286   g_main_add_poll (&watch->pollfd, priority);
287
288   return g_source_add (priority, TRUE, &unix_watch_funcs, watch, user_data, notify);
289 }
290
291 GIOChannel *
292 g_io_channel_unix_new (gint fd)
293 {
294   GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
295   GIOChannel *channel = (GIOChannel *)unix_channel;
296
297   g_io_channel_init (channel);
298   channel->funcs = &unix_channel_funcs;
299
300   unix_channel->fd = fd;
301   return channel;
302 }
303
304 gint
305 g_io_channel_unix_get_fd (GIOChannel *channel)
306 {
307   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
308   return unix_channel->fd;
309 }