1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gnome-vfs-open-fd.c - convert a file descriptor to a handle
4 Copyright (C) 2002 Giovanni Corriga
6 The Gnome Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The Gnome Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the Gnome Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Author: Giovanni Corriga <valkadesh@libero.it>
27 #include <sys/types.h>
31 #include "gnome-vfs-uri.h"
32 #include "gnome-vfs-method.h"
33 #include "gnome-vfs-handle.h"
34 #include "gnome-vfs-module-shared.h"
35 #include "gnome-vfs-mime.h"
36 #include "gnome-vfs-handle-private.h"
37 #include "gnome-vfs-utils.h"
40 create_anonymous_uri (GnomeVFSMethod* method)
42 GnomeVFSToplevelURI* tl_uri;
45 tl_uri = g_new0 (GnomeVFSToplevelURI, 1);
47 uri = (GnomeVFSURI *) tl_uri;
61 file_handle_new (GnomeVFSURI *uri,
65 result = g_new (FileHandle, 1);
67 result->uri = gnome_vfs_uri_ref (uri);
74 file_handle_destroy (FileHandle *handle)
76 gnome_vfs_uri_unref (handle->uri);
81 do_close (GnomeVFSMethod *method,
82 GnomeVFSMethodHandle *method_handle,
83 GnomeVFSContext *context)
85 FileHandle *file_handle;
88 g_return_val_if_fail (method_handle != NULL, GNOME_VFS_ERROR_INTERNAL);
90 file_handle = (FileHandle *) method_handle;
93 close_retval = close (file_handle->fd);
94 } while (close_retval != 0
96 && ! gnome_vfs_context_check_cancellation (context));
98 /* FIXME bugzilla.eazel.com 1163: Should do this even after a failure? */
99 file_handle_destroy (file_handle);
101 if (close_retval != 0) {
102 return gnome_vfs_result_from_errno ();
108 static GnomeVFSResult
109 do_read (GnomeVFSMethod *method,
110 GnomeVFSMethodHandle *method_handle,
112 GnomeVFSFileSize num_bytes,
113 GnomeVFSFileSize *bytes_read,
114 GnomeVFSContext *context)
116 FileHandle *file_handle;
119 g_return_val_if_fail (method_handle != NULL, GNOME_VFS_ERROR_INTERNAL);
121 file_handle = (FileHandle *) method_handle;
124 read_val = read (file_handle->fd, buffer, num_bytes);
125 } while (read_val == -1
127 && ! gnome_vfs_context_check_cancellation (context));
129 if (read_val == -1) {
131 return gnome_vfs_result_from_errno ();
133 *bytes_read = read_val;
135 /* Getting 0 from read() means EOF! */
137 return GNOME_VFS_ERROR_EOF;
143 static GnomeVFSResult
144 do_write (GnomeVFSMethod *method,
145 GnomeVFSMethodHandle *method_handle,
146 gconstpointer buffer,
147 GnomeVFSFileSize num_bytes,
148 GnomeVFSFileSize *bytes_written,
149 GnomeVFSContext *context)
151 FileHandle *file_handle;
154 g_return_val_if_fail (method_handle != NULL, GNOME_VFS_ERROR_INTERNAL);
156 file_handle = (FileHandle *) method_handle;
159 write_val = write (file_handle->fd, buffer, num_bytes);
160 } while (write_val == -1
162 && ! gnome_vfs_context_check_cancellation (context));
164 if (write_val == -1) {
166 return gnome_vfs_result_from_errno ();
168 *bytes_written = write_val;
175 seek_position_to_unix (GnomeVFSSeekPosition position)
178 case GNOME_VFS_SEEK_START:
180 case GNOME_VFS_SEEK_CURRENT:
182 case GNOME_VFS_SEEK_END:
185 return SEEK_SET; /* bogus */
189 static GnomeVFSResult
190 do_seek (GnomeVFSMethod *method,
191 GnomeVFSMethodHandle *method_handle,
192 GnomeVFSSeekPosition whence,
193 GnomeVFSFileOffset offset,
194 GnomeVFSContext *context)
196 FileHandle *file_handle;
199 file_handle = (FileHandle *) method_handle;
200 lseek_whence = seek_position_to_unix (whence);
202 if (lseek (file_handle->fd, offset, lseek_whence) == -1) {
203 if (errno == ESPIPE) {
204 return GNOME_VFS_ERROR_NOT_SUPPORTED;
206 return gnome_vfs_result_from_errno ();
213 static GnomeVFSResult
214 do_tell (GnomeVFSMethod *method,
215 GnomeVFSMethodHandle *method_handle,
216 GnomeVFSFileOffset *offset_return)
218 FileHandle *file_handle;
221 file_handle = (FileHandle *) method_handle;
223 offset = lseek (file_handle->fd, 0, SEEK_CUR);
225 if (errno == ESPIPE) {
226 return GNOME_VFS_ERROR_NOT_SUPPORTED;
228 return gnome_vfs_result_from_errno ();
232 *offset_return = offset;
237 static GnomeVFSResult
238 do_truncate_handle (GnomeVFSMethod *method,
239 GnomeVFSMethodHandle *method_handle,
240 GnomeVFSFileSize where,
241 GnomeVFSContext *context)
243 FileHandle *file_handle;
245 g_return_val_if_fail (method_handle != NULL, GNOME_VFS_ERROR_INTERNAL);
247 file_handle = (FileHandle *) method_handle;
249 if (ftruncate (file_handle->fd, where) == 0) {
255 return GNOME_VFS_ERROR_READ_ONLY;
257 return GNOME_VFS_ERROR_NOT_SUPPORTED;
259 return GNOME_VFS_ERROR_GENERIC;
264 static GnomeVFSResult
265 get_stat_info_from_handle (GnomeVFSFileInfo *file_info,
267 GnomeVFSFileInfoOptions options,
268 struct stat *statptr)
272 if (statptr == NULL) {
276 if (fstat (handle->fd, statptr) != 0) {
277 return gnome_vfs_result_from_errno ();
280 gnome_vfs_stat_to_file_info (file_info, statptr);
281 GNOME_VFS_FILE_INFO_SET_LOCAL (file_info, TRUE);
286 /* MIME detection code. */
288 get_mime_type (GnomeVFSFileInfo *info,
289 GnomeVFSFileInfoOptions options,
290 struct stat *stat_buffer)
292 const char *mime_type;
295 if ((options & GNOME_VFS_FILE_INFO_FOLLOW_LINKS) == 0
296 && (info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK)) {
297 /* we are a symlink and aren't asked to follow -
298 * return the type for a symlink
300 mime_type = "x-special/symlink";
302 mime_type = gnome_vfs_get_file_mime_type (NULL, stat_buffer,
303 (options & GNOME_VFS_FILE_INFO_FORCE_FAST_MIME_TYPE) != 0);
306 g_assert (mime_type);
307 info->mime_type = g_strdup (mime_type);
308 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
311 static GnomeVFSResult
312 do_get_file_info_from_handle (GnomeVFSMethod *method,
313 GnomeVFSMethodHandle *method_handle,
314 GnomeVFSFileInfo *file_info,
315 GnomeVFSFileInfoOptions options,
316 GnomeVFSContext *context)
318 FileHandle *file_handle;
320 GnomeVFSResult result;
322 file_handle = (FileHandle *) method_handle;
324 file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_NONE;
326 result = get_stat_info_from_handle (file_info, file_handle,
328 if (result != GNOME_VFS_OK) {
332 if (options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE) {
333 get_mime_type (file_info, options, &statbuf);
340 do_is_local (GnomeVFSMethod *method,
341 const GnomeVFSURI *uri)
346 static GnomeVFSMethod method = {
347 sizeof (GnomeVFSMethod),
349 NULL, /* do_create */
356 NULL, /* do_open_directory */
357 NULL, /* do_close_directory */
358 NULL, /* do_read_directory */
359 NULL, /* do_get_file_info */
360 do_get_file_info_from_handle,
362 NULL, /* do_make_directory */
363 NULL, /* do_remove_directory */
365 NULL, /* do_unlink */
366 NULL, /* do_check_same_fs */
367 NULL, /* do_set_file_info */
368 NULL, /* do_truncate */
369 NULL, /* do_find_directory */
370 NULL, /* do_create_symbolic_link */
371 NULL, /* do_monitor_add */
372 NULL, /* do_monitor_cancel */
375 static GnomeVFSOpenMode
376 get_open_mode (gint filedes)
380 flags = fcntl(filedes, F_GETFL);
381 if (flags & O_RDONLY) {
382 return GNOME_VFS_OPEN_READ;
383 } else if (flags & O_WRONLY) {
384 return GNOME_VFS_OPEN_WRITE;
385 } else if (flags & O_RDWR) {
386 return (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_WRITE);
389 return GNOME_VFS_OPEN_READ; /* bogus */
394 * @handle: A pointer to a pointer to a GnomeVFSHandle object
395 * @filedes: a UNIX file descriptor
397 * Converts an open unix file descript into a GnomeVFSHandle that
398 * can be used with the normal GnomeVFS file operations. When the
399 * handle is closed the file descriptor will also be closed.
401 * Return Value: %GNOME_VFS_OK if the open was ok, a suitable error otherwise.
407 gnome_vfs_open_fd (GnomeVFSHandle **handle, int filedes)
410 FileHandle* file_handle;
411 GnomeVFSOpenMode open_mode;
413 g_return_val_if_fail(handle != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
415 uri = create_anonymous_uri (&method);
417 open_mode = get_open_mode (filedes);
419 file_handle = file_handle_new (uri, filedes);
421 *handle = _gnome_vfs_handle_new (uri, (GnomeVFSMethodHandle*)file_handle, open_mode);
423 return GNOME_VFS_ERROR_INTERNAL;