]> git.proxmox.com Git - pve-cluster.git/blob - data/src/cfs-plug-func.c
c36968870155997b53578c39a10086dbc3edddf8
[pve-cluster.git] / data / src / cfs-plug-func.c
1 /*
2 Copyright (C) 2011 Proxmox Server Solutions GmbH
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
13
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 Author: Dietmar Maurer <dietmar@proxmox.com>
18
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif /* HAVE_CONFIG_H */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <glib.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/file.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <dirent.h>
36
37 #include "cfs-utils.h"
38 #include "cfs-plug.h"
39
40 static struct cfs_operations cfs_ops;
41
42 static cfs_plug_t *cfs_plug_func_lookup_plug(cfs_plug_t *plug, char **path)
43 {
44 g_return_val_if_fail(plug != NULL, NULL);
45 g_return_val_if_fail(plug->ops == &cfs_ops, NULL);
46
47 return (!*path || !(*path)[0]) ? plug : NULL;
48 }
49
50 static void cfs_plug_func_destroy(cfs_plug_t *plug)
51 {
52 g_return_if_fail(plug != NULL);
53 g_return_if_fail(plug->ops == &cfs_ops);
54
55 cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
56
57 cfs_debug("enter cfs_plug_func_destroy %s", plug->name);
58
59 if (fplug->data)
60 g_free(fplug->data);
61
62 g_free(plug->name);
63
64 g_free(plug);
65 }
66
67 static int
68 cfs_plug_func_getattr(
69 cfs_plug_t *plug,
70 const char *path,
71 struct stat *stbuf)
72 {
73 g_return_val_if_fail(plug != NULL, PARAM_CHECK_ERRNO);
74 g_return_val_if_fail(plug->ops == &cfs_ops, PARAM_CHECK_ERRNO);
75 g_return_val_if_fail(path != NULL, PARAM_CHECK_ERRNO);
76 g_return_val_if_fail(stbuf != NULL, PARAM_CHECK_ERRNO);
77
78 cfs_debug("enter cfs_plug_func_getattr %s", path);
79
80 cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
81
82 memset(stbuf, 0, sizeof(struct stat));
83
84 g_rw_lock_writer_lock(&fplug->data_rw_lock);
85 if (fplug->data)
86 g_free(fplug->data);
87
88 fplug->data = fplug->update_callback(plug);
89
90 stbuf->st_size = fplug->data ? strlen(fplug->data) : 0;
91
92 g_rw_lock_writer_unlock(&fplug->data_rw_lock);
93
94 stbuf->st_mode = fplug->mode;
95 stbuf->st_nlink = 1;
96
97 return 0;
98 }
99
100 static int
101 cfs_plug_func_read(
102 cfs_plug_t *plug,
103 const char *path,
104 char *buf,
105 size_t size,
106 off_t offset,
107 struct fuse_file_info *fi)
108 {
109 (void) fi;
110
111 g_return_val_if_fail(plug != NULL, PARAM_CHECK_ERRNO);
112 g_return_val_if_fail(plug->ops == &cfs_ops, PARAM_CHECK_ERRNO);
113 g_return_val_if_fail(path != NULL, PARAM_CHECK_ERRNO);
114 g_return_val_if_fail(buf != NULL, PARAM_CHECK_ERRNO);
115
116 cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
117
118 g_rw_lock_reader_lock(&fplug->data_rw_lock);
119 char *data = fplug->data;
120
121 cfs_debug("enter cfs_plug_func_read %s", data);
122
123 if (!data) {
124 g_rw_lock_reader_unlock(&fplug->data_rw_lock);
125 return 0;
126 }
127
128 int len = strlen(data);
129
130 if (offset < len) {
131 if (offset + size > len)
132 size = len - offset;
133 memcpy(buf, data + offset, size);
134 } else {
135 size = 0;
136 }
137 g_rw_lock_reader_unlock(&fplug->data_rw_lock);
138
139 return size;
140 }
141
142 static int
143 cfs_plug_func_write(
144 cfs_plug_t *plug,
145 const char *path,
146 const char *buf,
147 size_t size,
148 off_t offset,
149 struct fuse_file_info *fi)
150 {
151 (void) fi;
152
153 g_return_val_if_fail(plug != NULL, PARAM_CHECK_ERRNO);
154 g_return_val_if_fail(plug->ops == &cfs_ops, PARAM_CHECK_ERRNO);
155 g_return_val_if_fail(path != NULL, PARAM_CHECK_ERRNO);
156 g_return_val_if_fail(buf != NULL, PARAM_CHECK_ERRNO);
157
158 cfs_debug("enter cfs_plug_func_write");
159
160 cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
161
162 if (offset != 0 || !fplug->write_callback)
163 return -EIO;
164
165 return fplug->write_callback(plug, buf, size);
166 }
167
168 static int
169 cfs_plug_func_truncate(
170 cfs_plug_t *plug,
171 const char *path,
172 off_t size)
173 {
174 g_return_val_if_fail(plug != NULL, PARAM_CHECK_ERRNO);
175 g_return_val_if_fail(plug->ops == &cfs_ops, PARAM_CHECK_ERRNO);
176 g_return_val_if_fail(path != NULL, PARAM_CHECK_ERRNO);
177
178 cfs_plug_func_t *fplug = (cfs_plug_func_t *)plug;
179
180 if (fplug->write_callback)
181 return 0;
182
183 return -EIO;
184 }
185
186 static int
187 cfs_plug_func_open(
188 cfs_plug_t *plug,
189 const char *path,
190 struct fuse_file_info *fi)
191 {
192 g_return_val_if_fail(plug != NULL, PARAM_CHECK_ERRNO);
193 g_return_val_if_fail(plug->ops == &cfs_ops, PARAM_CHECK_ERRNO);
194 g_return_val_if_fail(path != NULL, PARAM_CHECK_ERRNO);
195 g_return_val_if_fail(fi != NULL, PARAM_CHECK_ERRNO);
196
197 cfs_debug("enter cfs_plug_func_open %s", path);
198
199 return 0;
200 }
201
202 static struct cfs_operations cfs_ops = {
203 .getattr = cfs_plug_func_getattr,
204 .read = cfs_plug_func_read,
205 .write = cfs_plug_func_write,
206 .truncate = cfs_plug_func_truncate,
207 .open = cfs_plug_func_open,
208 };
209
210
211 cfs_plug_func_t *
212 cfs_plug_func_new(
213 const char *name,
214 mode_t mode,
215 cfs_plug_func_udpate_data_fn_t update_callback,
216 cfs_plug_func_write_data_fn_t write_callback)
217 {
218 g_return_val_if_fail(name != NULL, NULL);
219 g_return_val_if_fail(update_callback != NULL, NULL);
220
221 cfs_plug_func_t *fplug = g_new0(cfs_plug_func_t, 1);
222
223 fplug->plug.ops = &cfs_ops;
224
225 fplug->plug.lookup_plug = cfs_plug_func_lookup_plug;
226 fplug->plug.destroy_plug = cfs_plug_func_destroy;
227
228 fplug->plug.name = g_strdup(name);
229
230 fplug->update_callback = update_callback;
231 fplug->write_callback = write_callback;
232 if (!write_callback)
233 mode = mode & ~0222;
234
235 fplug->mode = S_IFREG | mode;
236
237 return fplug;
238 }
239