Rename all struct members named: read, write, close, truncate, or mount to
[platform/upstream/glib.git] / gio / glocalfileinputstream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <errno.h>
32
33 #include <glib.h>
34 #include <glib/gstdio.h>
35 #include "gioerror.h"
36 #include "glocalfileinputstream.h"
37 #include "glocalfileinfo.h"
38 #include "glibintl.h"
39
40 #include "gioalias.h"
41
42 #define g_local_file_input_stream_get_type _g_local_file_input_stream_get_type
43 G_DEFINE_TYPE (GLocalFileInputStream, g_local_file_input_stream, G_TYPE_FILE_INPUT_STREAM);
44
45 struct _GLocalFileInputStreamPrivate {
46   int fd;
47 };
48
49 static gssize     g_local_file_input_stream_read       (GInputStream      *stream,
50                                                         void              *buffer,
51                                                         gsize              count,
52                                                         GCancellable      *cancellable,
53                                                         GError           **error);
54 static gssize     g_local_file_input_stream_skip       (GInputStream      *stream,
55                                                         gsize              count,
56                                                         GCancellable      *cancellable,
57                                                         GError           **error);
58 static gboolean   g_local_file_input_stream_close      (GInputStream      *stream,
59                                                         GCancellable      *cancellable,
60                                                         GError           **error);
61 static goffset    g_local_file_input_stream_tell       (GFileInputStream  *stream);
62 static gboolean   g_local_file_input_stream_can_seek   (GFileInputStream  *stream);
63 static gboolean   g_local_file_input_stream_seek       (GFileInputStream  *stream,
64                                                         goffset            offset,
65                                                         GSeekType          type,
66                                                         GCancellable      *cancellable,
67                                                         GError           **error);
68 static GFileInfo *g_local_file_input_stream_query_info (GFileInputStream  *stream,
69                                                         char              *attributes,
70                                                         GCancellable      *cancellable,
71                                                         GError           **error);
72
73 static void
74 g_local_file_input_stream_finalize (GObject *object)
75 {
76   GLocalFileInputStream *file;
77   
78   file = G_LOCAL_FILE_INPUT_STREAM (object);
79   
80   if (G_OBJECT_CLASS (g_local_file_input_stream_parent_class)->finalize)
81     (*G_OBJECT_CLASS (g_local_file_input_stream_parent_class)->finalize) (object);
82 }
83
84 static void
85 g_local_file_input_stream_class_init (GLocalFileInputStreamClass *klass)
86 {
87   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
88   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
89   GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
90   
91   g_type_class_add_private (klass, sizeof (GLocalFileInputStreamPrivate));
92   
93   gobject_class->finalize = g_local_file_input_stream_finalize;
94
95   stream_class->read_fn = g_local_file_input_stream_read;
96   stream_class->skip = g_local_file_input_stream_skip;
97   stream_class->close_fn = g_local_file_input_stream_close;
98   file_stream_class->tell = g_local_file_input_stream_tell;
99   file_stream_class->can_seek = g_local_file_input_stream_can_seek;
100   file_stream_class->seek = g_local_file_input_stream_seek;
101   file_stream_class->query_info = g_local_file_input_stream_query_info;
102 }
103
104 static void
105 g_local_file_input_stream_init (GLocalFileInputStream *info)
106 {
107   info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info,
108                                             G_TYPE_LOCAL_FILE_INPUT_STREAM,
109                                             GLocalFileInputStreamPrivate);
110 }
111
112 /**
113  * g_local_file_input_stream_new:
114  * @fd: File Descriptor.
115  * 
116  * Returns: #GFileInputStream for the given file descriptor.
117  **/
118 GFileInputStream *
119 _g_local_file_input_stream_new (int fd)
120 {
121   GLocalFileInputStream *stream;
122
123   stream = g_object_new (G_TYPE_LOCAL_FILE_INPUT_STREAM, NULL);
124   stream->priv->fd = fd;
125   
126   return G_FILE_INPUT_STREAM (stream);
127 }
128
129 static gssize
130 g_local_file_input_stream_read (GInputStream  *stream,
131                                 void          *buffer,
132                                 gsize          count,
133                                 GCancellable  *cancellable,
134                                 GError       **error)
135 {
136   GLocalFileInputStream *file;
137   gssize res;
138
139   file = G_LOCAL_FILE_INPUT_STREAM (stream);
140
141   res = -1;
142   while (1)
143     {
144       if (g_cancellable_set_error_if_cancelled (cancellable, error))
145         break;
146       res = read (file->priv->fd, buffer, count);
147       if (res == -1)
148         {
149           if (errno == EINTR)
150             continue;
151           
152           g_set_error (error, G_IO_ERROR,
153                        g_io_error_from_errno (errno),
154                        _("Error reading from file: %s"),
155                        g_strerror (errno));
156         }
157       
158       break;
159     }
160   
161   return res;
162 }
163
164 static gssize
165 g_local_file_input_stream_skip (GInputStream  *stream,
166                                 gsize          count,
167                                 GCancellable  *cancellable,
168                                 GError       **error)
169 {
170   off_t res, start;
171   GLocalFileInputStream *file;
172
173   file = G_LOCAL_FILE_INPUT_STREAM (stream);
174   
175   if (g_cancellable_set_error_if_cancelled (cancellable, error))
176     return -1;
177   
178   start = lseek (file->priv->fd, 0, SEEK_CUR);
179   if (start == -1)
180     {
181       g_set_error (error, G_IO_ERROR,
182                    g_io_error_from_errno (errno),
183                    _("Error seeking in file: %s"),
184                    g_strerror (errno));
185       return -1;
186     }
187   
188   res = lseek (file->priv->fd, count, SEEK_CUR);
189   if (res == -1)
190     {
191       g_set_error (error, G_IO_ERROR,
192                    g_io_error_from_errno (errno),
193                    _("Error seeking in file: %s"),
194                    g_strerror (errno));
195       return -1;
196     }
197
198   return res - start;
199 }
200
201 static gboolean
202 g_local_file_input_stream_close (GInputStream  *stream,
203                                  GCancellable  *cancellable,
204                                  GError       **error)
205 {
206   GLocalFileInputStream *file;
207   int res;
208
209   file = G_LOCAL_FILE_INPUT_STREAM (stream);
210
211   if (file->priv->fd == -1)
212     return TRUE;
213
214   while (1)
215     {
216       res = close (file->priv->fd);
217       if (res == -1)
218         g_set_error (error, G_IO_ERROR,
219                      g_io_error_from_errno (errno),
220                      _("Error closing file: %s"),
221                      g_strerror (errno));
222       break;
223     }
224
225   return res != -1;
226 }
227
228
229 static goffset
230 g_local_file_input_stream_tell (GFileInputStream *stream)
231 {
232   GLocalFileInputStream *file;
233   off_t pos;
234
235   file = G_LOCAL_FILE_INPUT_STREAM (stream);
236   
237   pos = lseek (file->priv->fd, 0, SEEK_CUR);
238
239   if (pos == (off_t)-1)
240     return 0;
241   
242   return pos;
243 }
244
245 static gboolean
246 g_local_file_input_stream_can_seek (GFileInputStream *stream)
247 {
248   GLocalFileInputStream *file;
249   off_t pos;
250
251   file = G_LOCAL_FILE_INPUT_STREAM (stream);
252   
253   pos = lseek (file->priv->fd, 0, SEEK_CUR);
254
255   if (pos == (off_t)-1 &&
256       errno == ESPIPE)
257     return FALSE;
258   
259   return TRUE;
260 }
261
262 static int
263 seek_type_to_lseek (GSeekType type)
264 {
265   switch (type)
266     {
267     default:
268     case G_SEEK_CUR:
269       return SEEK_CUR;
270       
271     case G_SEEK_SET:
272       return SEEK_SET;
273       
274     case G_SEEK_END:
275       return SEEK_END;
276     }
277 }
278
279 static gboolean
280 g_local_file_input_stream_seek (GFileInputStream  *stream,
281                                 goffset            offset,
282                                 GSeekType          type,
283                                 GCancellable      *cancellable,
284                                 GError           **error)
285 {
286   GLocalFileInputStream *file;
287   off_t pos;
288
289   file = G_LOCAL_FILE_INPUT_STREAM (stream);
290
291   pos = lseek (file->priv->fd, offset, seek_type_to_lseek (type));
292
293   if (pos == (off_t)-1)
294     {
295       g_set_error (error, G_IO_ERROR,
296                    g_io_error_from_errno (errno),
297                    _("Error seeking in file: %s"),
298                    g_strerror (errno));
299       return FALSE;
300     }
301   
302   return TRUE;
303 }
304
305 static GFileInfo *
306 g_local_file_input_stream_query_info (GFileInputStream  *stream,
307                                       char              *attributes,
308                                       GCancellable      *cancellable,
309                                       GError           **error)
310 {
311   GLocalFileInputStream *file;
312
313   file = G_LOCAL_FILE_INPUT_STREAM (stream);
314
315   if (g_cancellable_set_error_if_cancelled (cancellable, error))
316     return NULL;
317   
318   return _g_local_file_info_get_from_fd (file->priv->fd,
319                                          attributes,
320                                          error);
321 }