File: fusefs_fuse.c

package info (click to toggle)
ruby-fusefs 0.7.0-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 296 kB
  • sloc: ansic: 1,137; ruby: 760; sh: 8; makefile: 2
file content (150 lines) | stat: -rw-r--r-- 3,206 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* fusefs_fuse.c */

/* This is rewriting most of the things that occur
 * in fuse_main up through fuse_loop */

#define FUSE_USE_VERSION 26
#define _FILE_OFFSET_BITS 64

#include <fuse.h>
#include <fuse/fuse_lowlevel.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>
#include <stdint.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <signal.h>

struct fuse *fuse_instance = NULL;
struct fuse_chan *fusech = NULL;
static char *mounted_at = NULL;

static int set_one_signal_handler(int signal, void (*handler)(int));

int fusefs_fd() {
  if(fusech == NULL)
    return -1;
  return fuse_chan_fd(fusech);
}

int
fusefs_unmount() {
  char buf[128];

  if (mounted_at && fusech) {
    fuse_unmount(mounted_at, fusech);
    sprintf(buf, "/sbin/umount %s", mounted_at);
    system(buf);
  }
  if (fuse_instance)
    fuse_destroy(fuse_instance);
  fuse_instance = NULL;
  free(mounted_at);
  fusech = NULL;
}

static void
fusefs_ehandler() {
  if (fuse_instance != NULL) {
    fusefs_unmount();
  }
}

int
fusefs_setup(char *mountpoint, const struct fuse_operations *op, struct fuse_args *opts) {
  fusech = NULL;
  if (fuse_instance != NULL) {
    return 0;
  }
  if (mounted_at != NULL) {
    return 0;
  }

  /* First, mount us */
  fusech = fuse_mount(mountpoint, opts);
  if (fusech == NULL) return 0;

  fuse_instance = fuse_new(fusech, opts, op, sizeof(*op), NULL);
  if (fuse_instance == NULL)
    goto err_unmount;

  /* Set signal handlers */
  if (set_one_signal_handler(SIGHUP, fusefs_ehandler) == -1 ||
      set_one_signal_handler(SIGINT, fusefs_ehandler) == -1 ||
      set_one_signal_handler(SIGTERM, fusefs_ehandler) == -1 ||
      set_one_signal_handler(SIGPIPE, SIG_IGN) == -1)
    return 0;

  atexit(fusefs_ehandler);

  /* We've initialized it! */
  mounted_at = strdup(mountpoint);
  return 1;
err_destroy:
  fuse_destroy(fuse_instance);
err_unmount:
  fuse_unmount(mountpoint, fusech);
  return 0;
}

int
fusefs_uid() {
  struct fuse_context *context = fuse_get_context();
  if (context) return context->uid;
  return -1;
}

int
fusefs_gid() {
  struct fuse_context *context = fuse_get_context();
  if (context) return context->gid;
  return -1;
}

int
fusefs_process() {
  /* This gets exactly 1 command out of fuse fd. */
  /* Ideally, this is triggered after a select() returns */
  if (fuse_instance != NULL) {
    struct fuse_cmd *cmd;

    if (fuse_exited(fuse_instance))
      return 0;

    cmd = fuse_read_cmd(fuse_instance);
    if (cmd == NULL)
      return 1;

    fuse_process_cmd(fuse_instance, cmd);
  }
  return 1;
}


static int set_one_signal_handler(int signal, void (*handler)(int))
{
    struct sigaction sa;
    struct sigaction old_sa;

    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = handler;
    sigemptyset(&(sa.sa_mask));
    sa.sa_flags = 0;

    if (sigaction(signal, NULL, &old_sa) == -1) {
        perror("FUSE: cannot get old signal handler");
        return -1;
    }

    if (old_sa.sa_handler == SIG_DFL &&
        sigaction(signal, &sa, NULL) == -1) {
        perror("Cannot set signal handler");
        return -1;
    }
    return 0;
}