source: trunk/third/nautilus-cd-burner/mapping-method.c @ 21565

Revision 21565, 22.0 KB checked in by ghudson, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21564, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* mapping-method.c - VFS modules for handling remapped files
3 *
4 *  Copyright (C) 2002 Red Hat Inc,
5 *
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.
10 *
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.
15 *
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.
20 *
21 * Author: Alexander Larsson <alexl@redhat.com>
22 */
23
24#include "mapping-protocol.h"
25#include "mapping-method.h"
26#include <glib/ghash.h>
27#include <glib/glist.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <string.h>
32#include <errno.h>
33#include <fcntl.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <sys/un.h>
37#include <sys/poll.h>
38
39#include <libgnomevfs/gnome-vfs.h>
40#include <libgnomevfs/gnome-vfs-mime.h>
41#include <libgnomevfs/gnome-vfs-mime-utils.h>
42#include <libgnomevfs/gnome-vfs-ops.h>
43#include <libgnomevfs/gnome-vfs-cancellable-ops.h>
44
45#include <libgnomevfs/gnome-vfs-method.h>
46#include <libgnomevfs/gnome-vfs-module.h>
47#include <libgnomevfs/gnome-vfs-module-shared.h>
48
49int daemon_fd;
50static GMutex *mapping_lock = NULL;
51
52#define LAUNCH_DAEMON_TIMEOUT 2*1000
53
54#undef DEBUG_ENABLE
55
56#ifdef DEBUG_ENABLE
57#define DEBUG_PRINT(x) g_print x
58#else
59#define DEBUG_PRINT(x)
60#endif
61
62
63typedef struct {
64        char *root;
65        int pos;
66        char **listing;
67        int n_items;
68        char *dirname;
69        GnomeVFSFileInfoOptions options;
70} VirtualDirHandle;
71
72typedef struct {
73        GnomeVFSHandle *handle;
74        char *backing_file;
75} VirtualFileHandle;
76
77static gchar *
78get_path_from_uri (GnomeVFSURI const *uri)
79{
80        gchar *path;
81
82        path = gnome_vfs_unescape_string (uri->text,
83                G_DIR_SEPARATOR_S);
84               
85        if (path == NULL) {
86                return NULL;
87        }
88
89        if (path[0] != G_DIR_SEPARATOR) {
90                g_free (path);
91                return NULL;
92        }
93
94        return path;
95}
96
97static GnomeVFSURI *
98get_uri (char *path)
99{
100        char *text_uri;
101        GnomeVFSURI *uri;
102       
103        g_assert (path != NULL);
104
105        text_uri = gnome_vfs_get_uri_from_local_path (path);
106        uri = gnome_vfs_uri_new (text_uri);
107        g_free (text_uri);
108        return uri;
109}
110
111static GnomeVFSResult
112request_op (gint32 operation,
113            char *root,
114            char *path1,
115            char *path2,
116            gboolean option,
117            MappingReply *reply)
118{
119        int res;
120
121        g_mutex_lock (mapping_lock);
122        res = encode_request (daemon_fd,
123                              operation,
124                              root,
125                              path1,
126                              path2,
127                              option);
128        res = decode_reply (daemon_fd, reply);
129        g_mutex_unlock (mapping_lock);
130
131        return reply->result;
132}
133
134static GnomeVFSResult
135remove_file_helper (char *method, char *path)
136{
137        MappingReply reply;
138        GnomeVFSResult res;
139
140        res = request_op (MAPPING_REMOVE_FILE, method,
141                    path, NULL, FALSE, &reply);
142        destroy_reply (&reply);
143        return res;
144}
145
146static GnomeVFSResult
147do_open (GnomeVFSMethod *method,
148         GnomeVFSMethodHandle **method_handle,
149         GnomeVFSURI *uri,
150         GnomeVFSOpenMode mode,
151         GnomeVFSContext *context)
152{
153        GnomeVFSResult res;
154        GnomeVFSURI *file_uri = NULL;
155        GnomeVFSHandle *file_handle;
156        VirtualFileHandle *handle;
157        char *path;
158        MappingReply reply;
159
160        DEBUG_PRINT (("do_open: %s\n", gnome_vfs_uri_to_string (uri, 0)));
161       
162        *method_handle = NULL;
163        path = get_path_from_uri (uri);
164        if (path == NULL) {
165                return GNOME_VFS_ERROR_INVALID_URI;
166        }
167
168        res = request_op (MAPPING_GET_BACKING_FILE,
169                          uri->method_string,
170                          path,
171                          NULL,
172                          mode & GNOME_VFS_OPEN_WRITE,
173                          &reply);
174        g_free (path);
175
176               
177        if (res == GNOME_VFS_OK) {
178                file_uri = get_uri (reply.path);
179                res = gnome_vfs_open_uri_cancellable (&file_handle,
180                                                      file_uri, mode, context);
181
182                if (res == GNOME_VFS_OK) {
183                        handle = g_new (VirtualFileHandle, 1);
184                        handle->handle = file_handle;
185                        handle->backing_file = g_strdup (reply.path);
186                        *method_handle = (GnomeVFSMethodHandle *)handle;
187                }
188               
189                gnome_vfs_uri_unref (file_uri);
190        }
191
192        destroy_reply (&reply);
193       
194        return res;
195}
196
197static GnomeVFSResult
198do_create (GnomeVFSMethod *method,
199           GnomeVFSMethodHandle **method_handle,
200           GnomeVFSURI *uri,
201           GnomeVFSOpenMode mode,
202           gboolean exclusive,
203           guint perm,
204           GnomeVFSContext *context)
205{
206        GnomeVFSResult res;
207        GnomeVFSURI *file_uri;
208        char *path;
209        MappingReply reply;
210        gboolean newly_created;
211        GnomeVFSHandle *file_handle;
212        VirtualFileHandle *handle;
213       
214        DEBUG_PRINT (("do_create: %s\n", gnome_vfs_uri_to_string (uri, 0)))
215       
216        *method_handle = NULL;
217        path = get_path_from_uri (uri);
218        if (path == NULL) {
219                return GNOME_VFS_ERROR_INVALID_URI;
220        }
221
222        res = request_op (MAPPING_CREATE_FILE,
223                          uri->method_string,
224                          path, NULL,
225                          exclusive,
226                          &reply);
227        newly_created = reply.option;
228       
229        if (res == GNOME_VFS_OK) {
230                file_uri = get_uri (reply.path);
231                res = gnome_vfs_create_uri_cancellable
232                        (&file_handle,
233                         file_uri, mode, exclusive,
234                         perm, context);
235                gnome_vfs_uri_unref (file_uri);
236                if (res == GNOME_VFS_OK) {
237                        handle = g_new (VirtualFileHandle, 1);
238                        handle->handle = file_handle;
239                        handle->backing_file = g_strdup (reply.path);
240                        *method_handle = (GnomeVFSMethodHandle *)handle;
241                }
242
243        }
244       
245        destroy_reply (&reply);
246       
247
248        if (res != GNOME_VFS_OK && newly_created) {
249                        /* TODO: Remove the file that was created, since we failed */
250                        /* virtual_unlink (dir, file);
251                         * virtual_node_free (file, FALSE);
252                         */
253        }
254
255        return res;
256}
257
258static GnomeVFSResult
259do_close (GnomeVFSMethod *method,
260          GnomeVFSMethodHandle *method_handle,
261          GnomeVFSContext *context)
262
263{
264        DEBUG_PRINT (("do_close: %p\n", method_handle));
265        return gnome_vfs_close_cancellable (((VirtualFileHandle *)method_handle)->handle, context);
266}
267
268static GnomeVFSResult
269do_read (GnomeVFSMethod *method,
270         GnomeVFSMethodHandle *method_handle,
271         gpointer buffer,
272         GnomeVFSFileSize num_bytes,
273         GnomeVFSFileSize *bytes_read,
274         GnomeVFSContext *context)
275{
276        DEBUG_PRINT (("do_read: %p\n", method_handle));
277        return gnome_vfs_read_cancellable (((VirtualFileHandle *)method_handle)->handle,
278                                           buffer,
279                                           num_bytes,
280                                           bytes_read,
281                                           context);
282}
283
284static GnomeVFSResult
285do_write (GnomeVFSMethod *method,
286          GnomeVFSMethodHandle *method_handle,
287          gconstpointer buffer,
288          GnomeVFSFileSize num_bytes,
289          GnomeVFSFileSize *bytes_written,
290          GnomeVFSContext *context)
291{
292        DEBUG_PRINT (("do_write: %p\n", method_handle));
293        return gnome_vfs_write_cancellable
294                (((VirtualFileHandle *)method_handle)->handle,
295                 buffer,
296                 num_bytes,
297                 bytes_written,
298                 context);
299
300}
301
302static GnomeVFSResult
303do_seek (GnomeVFSMethod *method,
304         GnomeVFSMethodHandle *method_handle,
305         GnomeVFSSeekPosition whence,
306         GnomeVFSFileOffset offset,
307         GnomeVFSContext *context)
308{
309        DEBUG_PRINT (("do_seek: %p\n", method_handle));
310        return gnome_vfs_seek_cancellable
311                (((VirtualFileHandle *)method_handle)->handle,
312                 whence,
313                 offset,
314                 context);
315}
316
317static GnomeVFSResult
318do_tell (GnomeVFSMethod *method,
319         GnomeVFSMethodHandle *method_handle,
320         GnomeVFSFileOffset *offset_return)
321{
322        DEBUG_PRINT (("do_tell: %p\n", method_handle));
323        return gnome_vfs_tell (((VirtualFileHandle *)method_handle)->handle,
324                               offset_return);
325}
326
327static GnomeVFSResult
328do_truncate_handle (GnomeVFSMethod *method,
329                    GnomeVFSMethodHandle *method_handle,
330                    GnomeVFSFileSize where,
331                    GnomeVFSContext *context)
332{
333        DEBUG_PRINT (("do_truncate_handle: %p\n", method_handle));
334        return gnome_vfs_truncate_handle_cancellable (((VirtualFileHandle *)method_handle)->handle,
335                                                      where,
336                                                      context);
337}
338
339static GnomeVFSResult
340do_open_directory (GnomeVFSMethod *method,
341                   GnomeVFSMethodHandle **method_handle,
342                   GnomeVFSURI *uri,
343                   GnomeVFSFileInfoOptions options,
344                   GnomeVFSContext *context)
345{
346        char *path;
347        VirtualDirHandle *handle;
348        MappingReply reply;
349        GnomeVFSResult res;
350       
351
352        DEBUG_PRINT (("do_open_directory: %s\n", gnome_vfs_uri_to_string (uri, 0)));
353       
354        g_return_val_if_fail (uri != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
355
356        path = get_path_from_uri (uri);
357        if (path == NULL) {
358                return GNOME_VFS_ERROR_INVALID_URI;
359        }
360
361
362        res = request_op (MAPPING_LIST_DIR,
363                          uri->method_string,
364                          path, NULL,
365                          FALSE,
366                          &reply);
367       
368        if (res == GNOME_VFS_OK) {
369                handle = g_new (VirtualDirHandle, 1);
370
371                handle->pos = 0;
372                handle->dirname = path;
373                handle->listing = reply.strings;
374                g_assert ((reply.n_strings % 2) == 0);
375                handle->n_items = reply.n_strings/2;
376                handle->root = g_strdup (uri->method_string);
377                handle->options = options;
378               
379                *method_handle = (GnomeVFSMethodHandle *)handle;
380        } else {
381                g_free (path);
382        }
383       
384        destroy_reply (&reply);
385        return res;
386}
387
388static GnomeVFSResult
389do_close_directory (GnomeVFSMethod *method,
390                    GnomeVFSMethodHandle *method_handle,
391                    GnomeVFSContext *context)
392{
393        VirtualDirHandle *handle = (VirtualDirHandle *)method_handle;
394        int i;
395       
396        DEBUG_PRINT (("do_close_directory: %p\n", method_handle));
397        for (i = 0; i < handle->n_items*2; i++) {
398                g_free (handle->listing[i]);
399        }
400        g_free (handle->listing);
401        g_free (handle->root);
402        g_free (handle->dirname);
403        g_free (handle);
404        return GNOME_VFS_OK;
405}
406
407static void
408fill_in_directory_info (GnomeVFSFileInfo *file_info)
409{
410        file_info->valid_fields |=
411                GNOME_VFS_FILE_INFO_FIELDS_TYPE |
412                GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS |
413                GNOME_VFS_FILE_INFO_FIELDS_FLAGS |
414                GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
415
416        file_info->uid = getuid ();
417        file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
418        file_info->permissions = GNOME_VFS_PERM_USER_ALL | GNOME_VFS_PERM_OTHER_ALL;
419        file_info->flags = GNOME_VFS_FILE_FLAGS_LOCAL;
420        file_info->mime_type = g_strdup ("x-directory/normal");
421}
422
423static GnomeVFSResult
424do_read_directory (GnomeVFSMethod *method,
425                   GnomeVFSMethodHandle *method_handle,
426                   GnomeVFSFileInfo *file_info,
427                   GnomeVFSContext *context)
428{
429        VirtualDirHandle *handle = (VirtualDirHandle *)method_handle;
430        GnomeVFSResult res;
431        char *name;
432        char *backingfile;
433        char *path;
434        GnomeVFSURI *file_uri;
435
436        DEBUG_PRINT (("do_read_directory: %p\n", method_handle));
437
438        while (TRUE) {
439                if (handle->pos >= handle->n_items) {
440                        return GNOME_VFS_ERROR_EOF;
441                }
442
443                name = handle->listing[handle->pos*2];
444                backingfile = handle->listing[handle->pos*2+1];
445                ++handle->pos;
446
447                if (backingfile == NULL) {
448                        file_info->name = g_strdup (name);
449                        fill_in_directory_info (file_info);
450                        break;
451                }
452
453                file_uri = get_uri (backingfile);
454                res = gnome_vfs_get_file_info_uri_cancellable
455                        (file_uri, file_info, handle->options, context);
456                gnome_vfs_uri_unref (file_uri);
457
458                if (res == GNOME_VFS_ERROR_NOT_FOUND) {
459                        path = g_build_filename (handle->dirname, name, NULL);
460                        remove_file_helper (handle->root, path);
461                        g_free (path);
462                        continue;
463                }
464
465                g_free (file_info->name);
466                file_info->name = g_strdup (name);
467                break;
468        }
469       
470        return GNOME_VFS_OK;
471}
472
473static GnomeVFSResult
474do_get_file_info (GnomeVFSMethod *method,
475                  GnomeVFSURI *uri,
476                  GnomeVFSFileInfo *file_info,
477                  GnomeVFSFileInfoOptions options,
478                  GnomeVFSContext *context)
479{
480        GnomeVFSResult res;
481        GnomeVFSURI *file_uri = NULL;
482        char *path;
483        MappingReply reply;
484
485        DEBUG_PRINT (("do_get_file_info: %s\n", gnome_vfs_uri_to_string (uri, 0)));
486       
487        path = get_path_from_uri (uri);
488        if (path == NULL) {
489                return GNOME_VFS_ERROR_INVALID_URI;
490        }
491
492        res = request_op (MAPPING_GET_BACKING_FILE,
493                          uri->method_string,
494                          path,
495                          NULL,
496                          FALSE,
497                          &reply);
498               
499        if (res == GNOME_VFS_ERROR_IS_DIRECTORY) {
500                file_info->name = g_path_get_basename (path);
501                fill_in_directory_info (file_info);
502                res = GNOME_VFS_OK;
503        } else if (res == GNOME_VFS_OK) {
504                file_uri = get_uri (reply.path);
505                res = gnome_vfs_get_file_info_uri_cancellable
506                        (file_uri, file_info, options, context);
507                gnome_vfs_uri_unref (file_uri);
508
509                g_free (file_info->name);
510                file_info->name = g_path_get_basename (path);
511        }
512       
513        destroy_reply (&reply);
514        g_free (path);
515       
516        return res;
517}
518
519static GnomeVFSResult
520do_get_file_info_from_handle (GnomeVFSMethod *method,
521                              GnomeVFSMethodHandle *method_handle,
522                              GnomeVFSFileInfo *file_info,
523                              GnomeVFSFileInfoOptions options,
524                              GnomeVFSContext *context)
525{
526        GnomeVFSResult res;
527        DEBUG_PRINT (("do_get_file_info_from_handle: %p\n", method_handle));
528        res = gnome_vfs_get_file_info_from_handle_cancellable
529                (((VirtualFileHandle *)method_handle)->handle,
530                 file_info, options, context);
531        /* TODO: Need to fill out the real name here. Need to wrap method_handle */
532        return res;
533}
534
535static GnomeVFSResult
536do_make_directory (GnomeVFSMethod *method,
537                   GnomeVFSURI *uri,
538                   guint perm,
539                   GnomeVFSContext *context)
540{
541        GnomeVFSResult res;
542        char *path;
543        MappingReply reply;
544
545        DEBUG_PRINT (("do_make_directory: %s\n", gnome_vfs_uri_to_string (uri, 0)));
546       
547        path = get_path_from_uri (uri);
548        if (path == NULL) {
549                return GNOME_VFS_ERROR_INVALID_URI;
550        }
551
552       
553        res = request_op (MAPPING_CREATE_DIR,
554                          uri->method_string,
555                          path,
556                          NULL, FALSE,
557                          &reply);
558        g_free (path);
559        destroy_reply (&reply);
560
561        return res;
562}
563
564static GnomeVFSResult
565do_remove_directory (GnomeVFSMethod *method,
566                     GnomeVFSURI *uri,
567                     GnomeVFSContext *context)
568{
569        GnomeVFSResult res;
570        char *path;
571        MappingReply reply;
572
573        DEBUG_PRINT (("do_remove_directory: %s\n", gnome_vfs_uri_to_string (uri, 0)));
574       
575        path = get_path_from_uri (uri);
576        if (path == NULL) {
577                return GNOME_VFS_ERROR_INVALID_URI;
578        }
579
580       
581        res = request_op (MAPPING_REMOVE_DIR,
582                          uri->method_string,
583                          path,
584                          NULL, FALSE,
585                          &reply);
586        g_free (path);
587        destroy_reply (&reply);
588
589        return res;
590}
591
592static GnomeVFSResult
593do_unlink (GnomeVFSMethod *method,
594           GnomeVFSURI *uri,
595           GnomeVFSContext *context)
596{
597        GnomeVFSResult res;
598        char *path;
599
600        DEBUG_PRINT (("do_remove_directory: %s\n", gnome_vfs_uri_to_string (uri, 0)));
601       
602        path = get_path_from_uri (uri);
603        if (path == NULL) {
604                return GNOME_VFS_ERROR_INVALID_URI;
605        }
606
607        res = remove_file_helper (uri->method_string, path);
608        g_free (path);
609
610        return res;
611}
612
613static GnomeVFSResult
614do_move (GnomeVFSMethod *method,
615         GnomeVFSURI *old_uri,
616         GnomeVFSURI *new_uri,
617         gboolean force_replace,
618         GnomeVFSContext *context)
619{
620        GnomeVFSResult res;
621        MappingReply reply;
622        char *old_path;
623        char *new_path;
624
625        DEBUG_PRINT(("do_move (%s, %s)\n", gnome_vfs_uri_to_string (old_uri, 0), gnome_vfs_uri_to_string (new_uri, 0)));
626       
627        if (strcmp (new_uri->method_string,
628                    old_uri->method_string) != 0) {
629                return GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM;
630        }
631               
632        old_path = get_path_from_uri (old_uri);
633        if (old_path == NULL) {
634                return GNOME_VFS_ERROR_INVALID_URI;
635        }
636
637        new_path = get_path_from_uri (new_uri);
638        if (new_path == NULL) {
639                g_free (old_path);
640                return GNOME_VFS_ERROR_INVALID_URI;
641        }
642
643        res = request_op (MAPPING_MOVE_FILE,
644                          old_uri->method_string,
645                          old_path,
646                          new_path,
647                          FALSE,
648                          &reply);
649        destroy_reply (&reply);
650        g_free (old_path);
651        g_free (new_path);
652       
653        return res;
654}
655
656static gboolean
657do_is_local (GnomeVFSMethod *method,
658             const GnomeVFSURI *uri)
659{
660        return TRUE;
661}
662
663/* When checking whether two locations are on the same file system, we are
664   doing this to determine whether we can recursively move or do other
665   sorts of transfers.  When a symbolic link is the "source", its
666   location is the location of the link file, because we want to
667   know about transferring the link, whereas for symbolic links that
668   are "targets", we use the location of the object being pointed to,
669   because that is where we will be moving/copying to. */
670static GnomeVFSResult
671do_check_same_fs (GnomeVFSMethod *method,
672                  GnomeVFSURI *source_uri,
673                  GnomeVFSURI *target_uri,
674                  gboolean *same_fs_return,
675                  GnomeVFSContext *context)
676{
677        DEBUG_PRINT (("check_same_fs (%s, %s)\n", gnome_vfs_uri_to_string (source_uri, 0), gnome_vfs_uri_to_string (target_uri, 0)));
678        *same_fs_return = strcmp (source_uri->method_string,  target_uri->method_string) == 0;
679        return GNOME_VFS_OK;
680}
681
682
683static GnomeVFSResult
684do_set_file_info (GnomeVFSMethod *method,
685                  GnomeVFSURI *uri,
686                  const GnomeVFSFileInfo *info,
687                  GnomeVFSSetFileInfoMask mask,
688                  GnomeVFSContext *context)
689{
690        gchar *full_name;
691        GnomeVFSResult res;
692        MappingReply reply;
693        GnomeVFSURI *file_uri = NULL;
694       
695        DEBUG_PRINT (("do_set_file_info: %s\n", gnome_vfs_uri_to_string (uri, 0)));
696
697        full_name = get_path_from_uri (uri);
698        if (full_name == NULL) {
699                return GNOME_VFS_ERROR_INVALID_URI;
700        }
701
702        if (mask & GNOME_VFS_SET_FILE_INFO_NAME) {
703                gchar *dir, *encoded_dir;
704                gchar *new_name;
705
706                encoded_dir = gnome_vfs_uri_extract_dirname (uri);
707                dir = gnome_vfs_unescape_string (encoded_dir, G_DIR_SEPARATOR_S);
708                g_free (encoded_dir);
709                g_assert (dir != NULL);
710
711                /* FIXME bugzilla.eazel.com 645: This needs to return
712                 * an error for incoming names with "/" characters in
713                 * them, instead of moving the file.
714                 */
715
716                if (dir[strlen(dir) - 1] != '/') {
717                        new_name = g_strconcat (dir, "/", info->name, NULL);
718                } else {
719                        new_name = g_strconcat (dir, info->name, NULL);
720                }
721
722                res = request_op (MAPPING_MOVE_FILE,
723                                  uri->method_string,
724                                  full_name,
725                                  new_name,
726                                  FALSE,
727                                  &reply);
728                destroy_reply (&reply);
729
730                g_free (dir);
731               
732                g_free (full_name);
733                full_name = new_name;
734
735                if (res != GNOME_VFS_OK) {
736                        g_free (full_name);
737                        return res;
738                }
739                mask = mask & ~GNOME_VFS_SET_FILE_INFO_NAME;
740        }
741
742        if (mask != 0) {
743                res = request_op (MAPPING_GET_BACKING_FILE,
744                                  uri->method_string,
745                                  full_name,
746                                  NULL,
747                                  TRUE,
748                                  &reply);
749                g_free (full_name);
750                if (res != GNOME_VFS_OK) {
751                        destroy_reply (&reply);
752                        return res;
753                }
754
755                file_uri = get_uri (reply.path);
756                destroy_reply (&reply);
757               
758                res = gnome_vfs_set_file_info_cancellable (file_uri,
759                                                           info, mask, context);
760                gnome_vfs_uri_unref (file_uri);
761        }
762
763        return GNOME_VFS_OK;
764}
765
766static GnomeVFSResult
767do_truncate (GnomeVFSMethod *method,
768             GnomeVFSURI *uri,
769             GnomeVFSFileSize where,
770             GnomeVFSContext *context)
771{
772        GnomeVFSResult res;
773        GnomeVFSURI *file_uri = NULL;
774        char *path;
775        MappingReply reply;
776
777        DEBUG_PRINT (("do_truncate: %s\n", gnome_vfs_uri_to_string (uri, 0)));
778       
779        path = get_path_from_uri (uri);
780        if (path == NULL) {
781                return GNOME_VFS_ERROR_INVALID_URI;
782        }
783
784        res = request_op (MAPPING_GET_BACKING_FILE,
785                          uri->method_string,
786                          path,
787                          NULL,
788                          TRUE,
789                          &reply);
790
791               
792        if (res == GNOME_VFS_OK) {
793                file_uri = get_uri (reply.path);
794                res = gnome_vfs_truncate_uri_cancellable (file_uri, where, context);
795                gnome_vfs_uri_unref (file_uri);
796        }
797        destroy_reply (&reply);
798       
799        return res;
800}
801
802static GnomeVFSResult
803do_create_symbolic_link (GnomeVFSMethod *method,
804                         GnomeVFSURI *uri,
805                         const char *target_reference,
806                         GnomeVFSContext *context)
807{
808        GnomeVFSResult res;
809        MappingReply reply;
810        char *path;
811        char *target_path;
812       
813        DEBUG_PRINT (("do_create_symbolic_link: %s -> %s\n", gnome_vfs_uri_to_string (uri, 0), target_reference));
814       
815        path = get_path_from_uri (uri);
816        if (path == NULL) {
817                return GNOME_VFS_ERROR_INVALID_URI;
818        }
819
820        target_path = gnome_vfs_get_local_path_from_uri (target_reference);
821
822        if (target_path == NULL) {
823                g_free (path);
824                return GNOME_VFS_ERROR_NOT_SUPPORTED;
825        }
826       
827        res = request_op (MAPPING_CREATE_LINK,
828                          uri->method_string,
829                          path,
830                          target_path,
831                          FALSE,
832                          &reply);
833        destroy_reply (&reply);
834        g_free (target_path);
835        g_free (path);
836
837        return res;
838}
839
840static GnomeVFSResult
841do_file_control (GnomeVFSMethod *method,
842                 GnomeVFSMethodHandle *method_handle,
843                 const char *operation,
844                 gpointer operation_data,
845                 GnomeVFSContext *context)
846{
847        VirtualFileHandle *handle;
848
849        handle = (VirtualFileHandle *)method_handle;
850
851        if (strcmp (operation, "mapping:get_mapping") == 0) {
852                *(char **)operation_data = g_strdup (handle->backing_file);
853                return GNOME_VFS_OK;
854        }
855        return GNOME_VFS_ERROR_NOT_SUPPORTED;
856}
857
858
859static GnomeVFSMethod method = {
860        sizeof (GnomeVFSMethod),
861        do_open,
862        do_create,
863        do_close,
864        do_read,
865        do_write,
866        do_seek,
867        do_tell,
868        do_truncate_handle,
869        do_open_directory,
870        do_close_directory,
871        do_read_directory,
872        do_get_file_info,
873        do_get_file_info_from_handle,
874        do_is_local,
875        do_make_directory,
876        do_remove_directory,
877        do_move,
878        do_unlink,
879        do_check_same_fs,
880        do_set_file_info,
881        do_truncate,
882        NULL, /* do_find_directory */
883        do_create_symbolic_link,
884        NULL, /* do_monitor_add */
885        NULL, /* do_monitor_cancel */
886        do_file_control
887};
888
889static void
890daemon_child_setup (gpointer user_data)
891{
892        gint open_max;
893        gint i;
894        int *pipes = user_data;
895     
896        close (pipes[0]);
897        dup2 (pipes[1], 3);
898       
899        open_max = sysconf (_SC_OPEN_MAX);
900        for (i = 4; i < open_max; i++) {
901                fcntl (i, F_SETFD, FD_CLOEXEC);
902        }
903}
904
905static gboolean
906launch_daemon (void)
907{
908        GError *error;
909        gint pipes[2];
910        gchar *argv[] = {
911                LIBEXECDIR "/mapping-daemon",
912                NULL
913        };
914        struct pollfd pollfd;
915        char c;
916
917        if (pipe(pipes) != 0) {
918                g_warning ("pipe failure");
919                return FALSE;
920        }
921
922        error = NULL;
923        if (!g_spawn_async (NULL,
924                            argv, NULL,
925                            G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
926                            &daemon_child_setup, pipes,
927                            NULL,
928                            &error)) {
929                g_warning ("Couldn't launch mapping-daemon: %s\n",
930                           error->message);
931                g_error_free (error);
932                return FALSE;
933        }
934       
935        close (pipes[1]);
936
937        pollfd.fd = pipes[0];
938        pollfd.events = POLLIN;
939        pollfd.revents = 0;
940
941        if ( poll (&pollfd, 1, LAUNCH_DAEMON_TIMEOUT) != 1) {
942                g_warning ("Didn't get any signs from mapping-daemon\n");
943                return FALSE;
944        }
945        read (pipes[0], &c, 1);
946        close (pipes[0]);
947       
948        return TRUE;
949}
950
951
952GnomeVFSMethod *
953vfs_module_init (const char *method_name, const char *args)
954{
955        struct sockaddr_un sin;
956
957        sin.sun_family = AF_UNIX;
958        g_snprintf (sin.sun_path, sizeof(sin.sun_path), "%s/mapping-%s", g_get_tmp_dir (), g_get_user_name ());
959
960        if ((daemon_fd = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) {
961                perror("mapping method init - socket");
962                return NULL;
963        }
964       
965        if (connect (daemon_fd, (const struct sockaddr *) &sin, sizeof(sin)) == -1) {
966                if (errno == ECONNREFUSED || errno == ENOENT) {
967                        if (launch_daemon ()) {
968                                if (connect (daemon_fd,  (const struct sockaddr *) &sin, sizeof(sin)) == -1) {
969                                        perror("mapping method init - connect2");
970                                        return NULL;
971                                }
972                        } else {
973                                return NULL;
974                        }
975                } else {
976                        perror("mapping method init - connect");
977                        return NULL;
978                }
979        }
980
981        mapping_lock = g_mutex_new();
982       
983        return &method;
984}
985
986void
987vfs_module_shutdown (GnomeVFSMethod *method)
988{
989        close (daemon_fd);
990        g_mutex_free (mapping_lock);
991}
Note: See TracBrowser for help on using the repository browser.