Whitespace cleanups.
[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 #ifdef G_OS_WIN32
41 #include <io.h>
42 #endif
43
44 #include "gioalias.h"
45
46 #define g_local_file_input_stream_get_type _g_local_file_input_stream_get_type
47 G_DEFINE_TYPE (GLocalFileInputStream, g_local_file_input_stream, G_TYPE_FILE_INPUT_STREAM);
48
49 struct _GLocalFileInputStreamPrivate {
50   int fd;
51 };
52
53 static gssize     g_local_file_input_stream_read       (GInputStream      *stream,
54                                                         void              *buffer,
55                                                         gsize              count,
56                                                         GCancellable      *cancellable,
57                                                         GError           **error);
58 static gssize     g_local_file_input_stream_skip       (GInputStream      *stream,
59                                                         gsize              count,
60                                                         GCancellable      *cancellable,
61                                                         GError           **error);
62 static gboolean   g_local_file_input_stream_close      (GInputStream      *stream,
63                                                         GCancellable      *cancellable,
64                                                         GError           **error);
65 static goffset    g_local_file_input_stream_tell       (GFileInputStream  *stream);
66 static gboolean   g_local_file_input_stream_can_seek   (GFileInputStream  *stream);
67 static gboolean   g_local_file_input_stream_seek       (GFileInputStream  *stream,
68                                                         goffset            offset,
69                                                         GSeekType          type,
70                                                         GCancellable      *cancellable,
71                                                         GError           **error);
72 static GFileInfo *g_local_file_input_stream_query_info (GFileInputStream  *stream,
73                                                         char              *attributes,
74                                                         GCancellable      *cancellable,
75                                                         GError           **error);
76
77 static void
78 g_local_file_input_stream_finalize (GObject *object)
79 {
80   GLocalFileInputStream *file;
81   
82   file = G_LOCAL_FILE_INPUT_STREAM (object);
83   
84   if (G_OBJECT_CLASS (g_local_file_input_stream_parent_class)->finalize)
85     (*G_OBJECT_CLASS (g_local_file_input_stream_parent_class)->finalize) (object);
86 }
87
88 static void
89 g_local_file_input_stream_class_init (GLocalFileInputStreamClass *klass)
90 {
91   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
92   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
93   GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
94   
95   g_type_class_add_private (klass, sizeof (GLocalFileInputStreamPrivate));
96   
97   gobject_class->finalize = g_local_file_input_stream_finalize;
98
99   stream_class->read_fn = g_local_file_input_stream_read;
100   stream_class->skip = g_local_file_input_stream_skip;
101   stream_class->close_fn = g_local_file_input_stream_close;
102   file_stream_class->tell = g_local_file_input_stream_tell;
103   file_stream_class->can_seek = g_local_file_input_stream_can_seek;
104   file_stream_class->seek = g_local_file_input_stream_seek;
105   file_stream_class->query_info = g_local_file_input_stream_query_info;
106 }
107
108 static void
109 g_local_file_input_stream_init (GLocalFileInputStream *info)
110 {
111   info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info,
112                                             G_TYPE_LOCAL_FILE_INPUT_STREAM,
113                                             GLocalFileInputStreamPrivate);
114 }
115
116 /**
117  * g_local_file_input_stream_new:
118  * @fd: File Descriptor.
119  * 
120  * Returns: #GFileInputStream for the given file descriptor.
121  **/
122 GFileInputStream *
123 _g_local_file_input_stream_new (int fd)
124 {
125   GLocalFileInputStream *stream;
126
127   stream = g_object_new (G_TYPE_LOCAL_FILE_INPUT_STREAM, NULL);
128   stream->priv->fd = fd;
129   
130   return G_FILE_INPUT_STREAM (stream);
131 }
132
133 static gssize
134 g_local_file_input_stream_read (GInputStream  *stream,
135                                 void          *buffer,
136                                 gsize          count,
137                                 GCancellable  *cancellable,
138                                 GError       **error)
139 {
140   GLocalFileInputStream *file;
141   gssize res;
142
143   file = G_LOCAL_FILE_INPUT_STREAM (stream);
144
145   res = -1;
146   while (1)
147     {
148       if (g_cancellable_set_error_if_cancelled (cancellable, error))
149         break;
150       res = read (file->priv->fd, buffer, count);
151       if (res == -1)
152         {
153           if (errno == EINTR)
154             continue;
155           
156           g_set_error (error, G_IO_ERROR,
157                        g_io_error_from_errno (errno),
158                        _("Error reading from file: %s"),
159                        g_strerror (errno));
160         }
161       
162       break;
163     }
164   
165   return res;
166 }
167
168 static gssize
169 g_local_file_input_stream_skip (GInputStream  *stream,
170                                 gsize          count,
171                                 GCancellable  *cancellable,
172                                 GError       **error)
173 {
174   off_t res, start;
175   GLocalFileInputStream *file;
176
177   file = G_LOCAL_FILE_INPUT_STREAM (stream);
178   
179   if (g_cancellable_set_error_if_cancelled (cancellable, error))
180     return -1;
181   
182   start = lseek (file->priv->fd, 0, SEEK_CUR);
183   if (start == -1)
184     {
185       g_set_error (error, G_IO_ERROR,
186                    g_io_error_from_errno (errno),
187                    _("Error seeking in file: %s"),
188                    g_strerror (errno));
189       return -1;
190     }
191   
192   res = lseek (file->priv->fd, count, SEEK_CUR);
193   if (res == -1)
194     {
195       g_set_error (error, G_IO_ERROR,
196                    g_io_error_from_errno (errno),
197                    _("Error seeking in file: %s"),
198                    g_strerror (errno));
199       return -1;
200     }
201
202   return res - start;
203 }
204
205 static gboolean
206 g_local_file_input_stream_close (GInputStream  *stream,
207                                  GCancellable  *cancellable,
208                                  GError       **error)
209 {
210   GLocalFileInputStream *file;
211   int res;
212
213   file = G_LOCAL_FILE_INPUT_STREAM (stream);
214
215   if (file->priv->fd == -1)
216     return TRUE;
217
218   while (1)
219     {
220       res = close (file->priv->fd);
221       if (res == -1)
222         g_set_error (error, G_IO_ERROR,
223                      g_io_error_from_errno (errno),
224                      _("Error closing file: %s"),
225                      g_strerror (errno));
226       break;
227     }
228
229   return res != -1;
230 }
231
232
233 static goffset
234 g_local_file_input_stream_tell (GFileInputStream *stream)
235 {
236   GLocalFileInputStream *file;
237   off_t pos;
238
239   file = G_LOCAL_FILE_INPUT_STREAM (stream);
240   
241   pos = lseek (file->priv->fd, 0, SEEK_CUR);
242
243   if (pos == (off_t)-1)
244     return 0;
245   
246   return pos;
247 }
248
249 static gboolean
250 g_local_file_input_stream_can_seek (GFileInputStream *stream)
251 {
252   GLocalFileInputStream *file;
253   off_t pos;
254
255   file = G_LOCAL_FILE_INPUT_STREAM (stream);
256   
257   pos = lseek (file->priv->fd, 0, SEEK_CUR);
258
259   if (pos == (off_t)-1 && errno == ESPIPE)
260     return FALSE;
261   
262   return TRUE;
263 }
264
265 static int
266 seek_type_to_lseek (GSeekType type)
267 {
268   switch (type)
269     {
270     default:
271     case G_SEEK_CUR:
272       return SEEK_CUR;
273       
274     case G_SEEK_SET:
275       return SEEK_SET;
276       
277     case G_SEEK_END:
278       return SEEK_END;
279     }
280 }
281
282 static gboolean
283 g_local_file_input_stream_seek (GFileInputStream  *stream,
284                                 goffset            offset,
285                                 GSeekType          type,
286                                 GCancellable      *cancellable,
287                                 GError           **error)
288 {
289   GLocalFileInputStream *file;
290   off_t pos;
291
292   file = G_LOCAL_FILE_INPUT_STREAM (stream);
293
294   pos = lseek (file->priv->fd, offset, seek_type_to_lseek (type));
295
296   if (pos == (off_t)-1)
297     {
298       g_set_error (error, G_IO_ERROR,
299                    g_io_error_from_errno (errno),
300                    _("Error seeking in file: %s"),
301                    g_strerror (errno));
302       return FALSE;
303     }
304   
305   return TRUE;
306 }
307
308 static GFileInfo *
309 g_local_file_input_stream_query_info (GFileInputStream  *stream,
310                                       char              *attributes,
311                                       GCancellable      *cancellable,
312                                       GError           **error)
313 {
314   GLocalFileInputStream *file;
315
316   file = G_LOCAL_FILE_INPUT_STREAM (stream);
317
318   if (g_cancellable_set_error_if_cancelled (cancellable, error))
319     return NULL;
320   
321   return _g_local_file_info_get_from_fd (file->priv->fd,
322                                          attributes,
323                                          error);
324 }