Imported Upstream version 2.74.3
[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  * SPDX-License-Identifier: LGPL-2.1-or-later
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
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 "config.h"
35
36 #define _POSIX_SOURCE           /* for SSIZE_MAX */
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <string.h>
44 #include <fcntl.h>
45 #include <glib/gstdio.h>
46
47 #include "giochannel.h"
48
49 #include "gerror.h"
50 #include "gfileutils.h"
51 #include "gstrfuncs.h"
52 #include "gtestutils.h"
53
54 /*
55  * Unix IO Channels
56  */
57
58 typedef struct _GIOUnixChannel GIOUnixChannel;
59 typedef struct _GIOUnixWatch GIOUnixWatch;
60
61 struct _GIOUnixChannel
62 {
63   GIOChannel channel;
64   gint fd;
65 };
66
67 struct _GIOUnixWatch
68 {
69   GSource       source;
70   GPollFD       pollfd;
71   GIOChannel   *channel;
72   GIOCondition  condition;
73 };
74
75
76 static GIOStatus        g_io_unix_read          (GIOChannel   *channel,
77                                                  gchar        *buf,
78                                                  gsize         count,
79                                                  gsize        *bytes_read,
80                                                  GError      **err);
81 static GIOStatus        g_io_unix_write         (GIOChannel   *channel,
82                                                  const gchar  *buf,
83                                                  gsize         count,
84                                                  gsize        *bytes_written,
85                                                  GError      **err);
86 static GIOStatus        g_io_unix_seek          (GIOChannel   *channel,
87                                                  gint64        offset,
88                                                  GSeekType     type,
89                                                  GError      **err);
90 static GIOStatus        g_io_unix_close         (GIOChannel   *channel,
91                                                  GError      **err);
92 static void             g_io_unix_free          (GIOChannel   *channel);
93 static GSource*         g_io_unix_create_watch  (GIOChannel   *channel,
94                                                  GIOCondition  condition);
95 static GIOStatus        g_io_unix_set_flags     (GIOChannel   *channel,
96                                                  GIOFlags      flags,
97                                                  GError      **err);
98 static GIOFlags         g_io_unix_get_flags     (GIOChannel   *channel);
99
100 static gboolean g_io_unix_prepare  (GSource     *source,
101                                     gint        *timeout);
102 static gboolean g_io_unix_check    (GSource     *source);
103 static gboolean g_io_unix_dispatch (GSource     *source,
104                                     GSourceFunc  callback,
105                                     gpointer     user_data);
106 static void     g_io_unix_finalize (GSource     *source);
107
108 GSourceFuncs g_io_watch_funcs = {
109   g_io_unix_prepare,
110   g_io_unix_check,
111   g_io_unix_dispatch,
112   g_io_unix_finalize,
113   NULL, NULL
114 };
115
116 static GIOFuncs unix_channel_funcs = {
117   g_io_unix_read,
118   g_io_unix_write,
119   g_io_unix_seek,
120   g_io_unix_close,
121   g_io_unix_create_watch,
122   g_io_unix_free,
123   g_io_unix_set_flags,
124   g_io_unix_get_flags,
125 };
126
127 static gboolean 
128 g_io_unix_prepare (GSource  *source,
129                    gint     *timeout)
130 {
131   GIOUnixWatch *watch = (GIOUnixWatch *)source;
132   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
133
134   *timeout = -1;
135
136   /* Only return TRUE here if _all_ bits in watch->condition will be set
137    */
138   return ((watch->condition & buffer_condition) == watch->condition);
139 }
140
141 static gboolean 
142 g_io_unix_check (GSource  *source)
143 {
144   GIOUnixWatch *watch = (GIOUnixWatch *)source;
145   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
146   GIOCondition poll_condition = watch->pollfd.revents;
147
148   return ((poll_condition | buffer_condition) & watch->condition);
149 }
150
151 static gboolean
152 g_io_unix_dispatch (GSource     *source,
153                     GSourceFunc  callback,
154                     gpointer     user_data)
155
156 {
157   GIOFunc func = (GIOFunc)callback;
158   GIOUnixWatch *watch = (GIOUnixWatch *)source;
159   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
160
161   if (!func)
162     {
163       g_warning ("IO watch dispatched without callback. "
164                  "You must call g_source_connect().");
165       return FALSE;
166     }
167   
168   return (*func) (watch->channel,
169                   (watch->pollfd.revents | buffer_condition) & watch->condition,
170                   user_data);
171 }
172
173 static void 
174 g_io_unix_finalize (GSource *source)
175 {
176   GIOUnixWatch *watch = (GIOUnixWatch *)source;
177
178   g_io_channel_unref (watch->channel);
179 }
180
181 static GIOStatus
182 g_io_unix_read (GIOChannel *channel, 
183                 gchar      *buf, 
184                 gsize       count,
185                 gsize      *bytes_read,
186                 GError    **err)
187 {
188   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
189   gssize result;
190
191   if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
192     count = SSIZE_MAX;
193
194  retry:
195   result = read (unix_channel->fd, buf, count);
196
197   if (result < 0)
198     {
199       int errsv = errno;
200       *bytes_read = 0;
201
202       switch (errsv)
203         {
204 #ifdef EINTR
205           case EINTR:
206             goto retry;
207 #endif
208 #ifdef EAGAIN
209           case EAGAIN:
210             return G_IO_STATUS_AGAIN;
211 #endif
212           default:
213             g_set_error_literal (err, G_IO_CHANNEL_ERROR,
214                                  g_io_channel_error_from_errno (errsv),
215                                  g_strerror (errsv));
216             return G_IO_STATUS_ERROR;
217         }
218     }
219
220   *bytes_read = result;
221
222   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
223 }
224
225 static GIOStatus
226 g_io_unix_write (GIOChannel  *channel, 
227                  const gchar *buf, 
228                  gsize       count,
229                  gsize      *bytes_written,
230                  GError    **err)
231 {
232   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
233   gssize result;
234
235  retry:
236   result = write (unix_channel->fd, buf, count);
237
238   if (result < 0)
239     {
240       int errsv = errno;
241       *bytes_written = 0;
242
243       switch (errsv)
244         {
245 #ifdef EINTR
246           case EINTR:
247             goto retry;
248 #endif
249 #ifdef EAGAIN
250           case EAGAIN:
251             return G_IO_STATUS_AGAIN;
252 #endif
253           default:
254             g_set_error_literal (err, G_IO_CHANNEL_ERROR,
255                                  g_io_channel_error_from_errno (errsv),
256                                  g_strerror (errsv));
257             return G_IO_STATUS_ERROR;
258         }
259     }
260
261   *bytes_written = result;
262
263   return G_IO_STATUS_NORMAL;
264 }
265
266 static GIOStatus
267 g_io_unix_seek (GIOChannel *channel,
268                 gint64      offset, 
269                 GSeekType   type,
270                 GError    **err)
271 {
272   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
273   int whence;
274   off_t tmp_offset;
275   off_t result;
276
277   switch (type)
278     {
279     case G_SEEK_SET:
280       whence = SEEK_SET;
281       break;
282     case G_SEEK_CUR:
283       whence = SEEK_CUR;
284       break;
285     case G_SEEK_END:
286       whence = SEEK_END;
287       break;
288     default:
289       whence = -1; /* Shut the compiler up */
290       g_assert_not_reached ();
291     }
292
293   tmp_offset = offset;
294   if (tmp_offset != offset)
295     {
296       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
297                            g_io_channel_error_from_errno (EINVAL),
298                            g_strerror (EINVAL));
299       return G_IO_STATUS_ERROR;
300     }
301   
302   result = lseek (unix_channel->fd, tmp_offset, whence);
303
304   if (result < 0)
305     {
306       int errsv = errno;
307       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
308                            g_io_channel_error_from_errno (errsv),
309                            g_strerror (errsv));
310       return G_IO_STATUS_ERROR;
311     }
312
313   return G_IO_STATUS_NORMAL;
314 }
315
316
317 static GIOStatus
318 g_io_unix_close (GIOChannel *channel,
319                  GError    **err)
320 {
321   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
322
323   if (close (unix_channel->fd) < 0)
324     {
325       int errsv = errno;
326       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
327                            g_io_channel_error_from_errno (errsv),
328                            g_strerror (errsv));
329       return G_IO_STATUS_ERROR;
330     }
331
332   return G_IO_STATUS_NORMAL;
333 }
334
335 static void 
336 g_io_unix_free (GIOChannel *channel)
337 {
338   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
339
340   g_free (unix_channel);
341 }
342
343 static GSource *
344 g_io_unix_create_watch (GIOChannel   *channel,
345                         GIOCondition  condition)
346 {
347   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
348   GSource *source;
349   GIOUnixWatch *watch;
350
351
352   source = g_source_new (&g_io_watch_funcs, sizeof (GIOUnixWatch));
353   g_source_set_static_name (source, "GIOChannel (Unix)");
354   watch = (GIOUnixWatch *)source;
355   
356   watch->channel = channel;
357   g_io_channel_ref (channel);
358   
359   watch->condition = condition;
360
361   watch->pollfd.fd = unix_channel->fd;
362   watch->pollfd.events = condition;
363
364   g_source_add_poll (source, &watch->pollfd);
365
366   return source;
367 }
368
369 static GIOStatus
370 g_io_unix_set_flags (GIOChannel *channel,
371                      GIOFlags    flags,
372                      GError    **err)
373 {
374   glong fcntl_flags;
375   GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
376
377   fcntl_flags = 0;
378
379   if (flags & G_IO_FLAG_APPEND)
380     fcntl_flags |= O_APPEND;
381   if (flags & G_IO_FLAG_NONBLOCK)
382 #ifdef O_NONBLOCK
383     fcntl_flags |= O_NONBLOCK;
384 #else
385     fcntl_flags |= O_NDELAY;
386 #endif
387
388   if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
389     {
390       int errsv = errno;
391       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
392                            g_io_channel_error_from_errno (errsv),
393                            g_strerror (errsv));
394       return G_IO_STATUS_ERROR;
395     }
396
397   return G_IO_STATUS_NORMAL;
398 }
399
400 static GIOFlags
401 g_io_unix_get_flags (GIOChannel *channel)
402 {
403   GIOFlags flags = G_IO_FLAG_NONE;
404   glong fcntl_flags;
405   GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
406
407   fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
408
409   if (fcntl_flags == -1)
410     {
411       int err = errno;
412       g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)",
413                  g_strerror (err), err);
414       return 0;
415     }
416
417   if (fcntl_flags & O_APPEND)
418     flags |= G_IO_FLAG_APPEND;
419 #ifdef O_NONBLOCK
420   if (fcntl_flags & O_NONBLOCK)
421 #else
422   if (fcntl_flags & O_NDELAY)
423 #endif
424     flags |= G_IO_FLAG_NONBLOCK;
425
426   switch (fcntl_flags & (O_RDONLY | O_WRONLY | O_RDWR))
427     {
428       case O_RDONLY:
429         channel->is_readable = TRUE;
430         channel->is_writeable = FALSE;
431         break;
432       case O_WRONLY:
433         channel->is_readable = FALSE;
434         channel->is_writeable = TRUE;
435         break;
436       case O_RDWR:
437         channel->is_readable = TRUE;
438         channel->is_writeable = TRUE;
439         break;
440       default:
441         g_assert_not_reached ();
442     }
443
444   return flags;
445 }
446
447 GIOChannel *
448 g_io_channel_new_file (const gchar *filename,
449                        const gchar *mode,
450                        GError     **error)
451 {
452   int fid, flags;
453   mode_t create_mode;
454   GIOChannel *channel;
455   enum { /* Cheesy hack */
456     MODE_R = 1 << 0,
457     MODE_W = 1 << 1,
458     MODE_A = 1 << 2,
459     MODE_PLUS = 1 << 3,
460     MODE_R_PLUS = MODE_R | MODE_PLUS,
461     MODE_W_PLUS = MODE_W | MODE_PLUS,
462     MODE_A_PLUS = MODE_A | MODE_PLUS
463   } mode_num;
464   struct stat buffer;
465
466   g_return_val_if_fail (filename != NULL, NULL);
467   g_return_val_if_fail (mode != NULL, NULL);
468   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
469
470   switch (mode[0])
471     {
472       case 'r':
473         mode_num = MODE_R;
474         break;
475       case 'w':
476         mode_num = MODE_W;
477         break;
478       case 'a':
479         mode_num = MODE_A;
480         break;
481       default:
482         g_warning ("Invalid GIOFileMode %s.", mode);
483         return NULL;
484     }
485
486   switch (mode[1])
487     {
488       case '\0':
489         break;
490       case '+':
491         if (mode[2] == '\0')
492           {
493             mode_num |= MODE_PLUS;
494             break;
495           }
496         G_GNUC_FALLTHROUGH;
497       default:
498         g_warning ("Invalid GIOFileMode %s.", mode);
499         return NULL;
500     }
501
502   switch (mode_num)
503     {
504       case MODE_R:
505         flags = O_RDONLY;
506         break;
507       case MODE_W:
508         flags = O_WRONLY | O_TRUNC | O_CREAT;
509         break;
510       case MODE_A:
511         flags = O_WRONLY | O_APPEND | O_CREAT;
512         break;
513       case MODE_R_PLUS:
514         flags = O_RDWR;
515         break;
516       case MODE_W_PLUS:
517         flags = O_RDWR | O_TRUNC | O_CREAT;
518         break;
519       case MODE_A_PLUS:
520         flags = O_RDWR | O_APPEND | O_CREAT;
521         break;
522       case MODE_PLUS:
523       default:
524         g_assert_not_reached ();
525         flags = 0;
526     }
527
528   create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
529
530   fid = g_open (filename, flags, create_mode);
531   if (fid == -1)
532     {
533       int err = errno;
534       g_set_error_literal (error, G_FILE_ERROR,
535                            g_file_error_from_errno (err),
536                            g_strerror (err));
537       return (GIOChannel *)NULL;
538     }
539
540   if (fstat (fid, &buffer) == -1) /* In case someone opens a FIFO */
541     {
542       int err = errno;
543       close (fid);
544       g_set_error_literal (error, G_FILE_ERROR,
545                            g_file_error_from_errno (err),
546                            g_strerror (err));
547       return (GIOChannel *)NULL;
548     }
549
550   channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
551
552   channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
553                          || S_ISBLK (buffer.st_mode);
554
555   switch (mode_num)
556     {
557       case MODE_R:
558         channel->is_readable = TRUE;
559         channel->is_writeable = FALSE;
560         break;
561       case MODE_W:
562       case MODE_A:
563         channel->is_readable = FALSE;
564         channel->is_writeable = TRUE;
565         break;
566       case MODE_R_PLUS:
567       case MODE_W_PLUS:
568       case MODE_A_PLUS:
569         channel->is_readable = TRUE;
570         channel->is_writeable = TRUE;
571         break;
572       case MODE_PLUS:
573       default:
574         g_assert_not_reached ();
575     }
576
577   g_io_channel_init (channel);
578   channel->close_on_unref = TRUE; /* must be after g_io_channel_init () */
579   channel->funcs = &unix_channel_funcs;
580
581   ((GIOUnixChannel *) channel)->fd = fid;
582   return channel;
583 }
584
585 /**
586  * g_io_channel_unix_new:
587  * @fd: a file descriptor.
588  *
589  * Creates a new #GIOChannel given a file descriptor. On UNIX systems
590  * this works for plain files, pipes, and sockets.
591  *
592  * The returned #GIOChannel has a reference count of 1.
593  *
594  * The default encoding for #GIOChannel is UTF-8. If your application
595  * is reading output from a command using via pipe, you may need to set
596  * the encoding to the encoding of the current locale (see
597  * g_get_charset()) with the g_io_channel_set_encoding() function.
598  * By default, the fd passed will not be closed when the final reference
599  * to the #GIOChannel data structure is dropped.
600  *
601  * If you want to read raw binary data without interpretation, then
602  * call the g_io_channel_set_encoding() function with %NULL for the
603  * encoding argument.
604  *
605  * This function is available in GLib on Windows, too, but you should
606  * avoid using it on Windows. The domain of file descriptors and
607  * sockets overlap. There is no way for GLib to know which one you mean
608  * in case the argument you pass to this function happens to be both a
609  * valid file descriptor and socket. If that happens a warning is
610  * issued, and GLib assumes that it is the file descriptor you mean.
611  *
612  * Returns: a new #GIOChannel.
613  **/
614 GIOChannel *
615 g_io_channel_unix_new (gint fd)
616 {
617   struct stat buffer;
618   GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
619   GIOChannel *channel = (GIOChannel *)unix_channel;
620
621   g_io_channel_init (channel);
622   channel->funcs = &unix_channel_funcs;
623
624   unix_channel->fd = fd;
625
626   /* I'm not sure if fstat on a non-file (e.g., socket) works
627    * it should be safe to say if it fails, the fd isn't seekable.
628    */
629   /* Newer UNIX versions support S_ISSOCK(), fstat() will probably
630    * succeed in most cases.
631    */
632   if (fstat (unix_channel->fd, &buffer) == 0)
633     channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
634                            || S_ISBLK (buffer.st_mode);
635   else /* Assume not seekable */
636     channel->is_seekable = FALSE;
637
638   g_io_unix_get_flags (channel); /* Sets is_readable, is_writeable */
639
640   return channel;
641 }
642
643 /**
644  * g_io_channel_unix_get_fd:
645  * @channel: a #GIOChannel, created with g_io_channel_unix_new().
646  *
647  * Returns the file descriptor of the #GIOChannel.
648  *
649  * On Windows this function returns the file descriptor or socket of
650  * the #GIOChannel.
651  *
652  * Returns: the file descriptor of the #GIOChannel.
653  **/
654 gint
655 g_io_channel_unix_get_fd (GIOChannel *channel)
656 {
657   GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
658   return unix_channel->fd;
659 }