1 #include "dbfs.h" |
|
2 |
|
3 /* |
|
4 * Handling simple ino-related ops, like lookup, readlink, unlink and link |
|
5 */ |
|
6 |
|
7 #include "../lib/log.h" |
|
8 #include "../lib/misc.h" |
|
9 |
|
10 /* |
|
11 * Used for lookup and link |
|
12 */ |
|
13 void dbfs_entry_res (const struct evsql_result_info *res, void *arg) { |
|
14 struct fuse_req *req = arg; |
|
15 struct fuse_entry_param e; ZINIT(e); |
|
16 int err = 0; |
|
17 |
|
18 uint32_t ino; |
|
19 |
|
20 // check the results |
|
21 if ((err = _dbfs_check_res(res, 1, 5))) |
|
22 SERROR(err = (err == 1 ? ENOENT : EIO)); |
|
23 |
|
24 // get the data |
|
25 if (0 |
|
26 || evsql_result_uint32(res, 0, 0, &ino, 0 ) // inodes.ino |
|
27 ) |
|
28 EERROR(err = EIO, "invalid db data"); |
|
29 |
|
30 INFO("\t[dbfs.lookup] -> ino=%u", ino); |
|
31 |
|
32 // stat attrs |
|
33 if ((err = _dbfs_stat_info(&e.attr, res, 0, 1))) |
|
34 goto error; |
|
35 |
|
36 // other attrs |
|
37 e.ino = e.attr.st_ino = ino; |
|
38 e.attr_timeout = CACHE_TIMEOUT; |
|
39 e.entry_timeout = CACHE_TIMEOUT; |
|
40 |
|
41 // reply |
|
42 if ((err = -fuse_reply_entry(req, &e))) |
|
43 EERROR(err, "fuse_reply_entry"); |
|
44 |
|
45 error: |
|
46 if (err && (err = -fuse_reply_err(req, err))) |
|
47 EWARNING(err, "fuse_reply_err"); |
|
48 |
|
49 // free |
|
50 evsql_result_free(res); |
|
51 } |
|
52 |
|
53 void dbfs_lookup (struct fuse_req *req, fuse_ino_t parent, const char *name) { |
|
54 struct dbfs *ctx = fuse_req_userdata(req); |
|
55 struct evsql_query *query; |
|
56 int err; |
|
57 |
|
58 INFO("[dbfs.lookup] parent=%lu name=%s", parent, name); |
|
59 |
|
60 // query and params |
|
61 const char *sql = |
|
62 "SELECT" |
|
63 " inodes.ino, " DBFS_STAT_COLS |
|
64 " FROM file_tree INNER JOIN inodes ON (file_tree.ino = inodes.ino)" |
|
65 " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar"; |
|
66 |
|
67 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
|
68 EVSQL_PARAM ( UINT32 ), |
|
69 EVSQL_PARAM ( STRING ), |
|
70 |
|
71 EVSQL_PARAMS_END |
|
72 }; |
|
73 |
|
74 // build params |
|
75 if (0 |
|
76 || evsql_param_uint32(¶ms, 0, parent) |
|
77 || evsql_param_string(¶ms, 1, name) |
|
78 ) |
|
79 EERROR(err = EIO, "evsql_param_*"); |
|
80 |
|
81 // query |
|
82 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, dbfs_entry_res, req)) == NULL) |
|
83 EERROR(err = EIO, "evsql_query_params"); |
|
84 |
|
85 // handle interrupts |
|
86 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
|
87 |
|
88 // wait |
|
89 return; |
|
90 |
|
91 error: |
|
92 if ((err = -fuse_reply_err(req, err))) |
|
93 EWARNING(err, "fuse_reply_err"); |
|
94 } |
|
95 |
|
96 void _dbfs_readlink_res (const struct evsql_result_info *res, void *arg) { |
|
97 struct fuse_req *req = arg; |
|
98 int err = 0; |
|
99 |
|
100 uint32_t ino; |
|
101 const char *type, *link; |
|
102 |
|
103 // check the results |
|
104 if ((err = _dbfs_check_res(res, 1, 3))) |
|
105 SERROR(err = (err == 1 ? ENOENT : EIO)); |
|
106 |
|
107 // get our data |
|
108 if (0 |
|
109 || evsql_result_uint32(res, 0, 0, &ino, 0 ) // inodes.ino |
|
110 || evsql_result_string(res, 0, 1, &type, 0 ) // inodes.type |
|
111 || evsql_result_string(res, 0, 2, &link, 1 ) // inodes.link_path |
|
112 ) |
|
113 EERROR(err = EIO, "invalid db data"); |
|
114 |
|
115 // is it a symlink? |
|
116 if (_dbfs_mode(type) != S_IFLNK) |
|
117 EERROR(err = EINVAL, "wrong type: %s", type); |
|
118 |
|
119 INFO("\t[dbfs.readlink %p] -> ino=%lu, type=%s, link=%s", req, (unsigned long int) ino, type, link); |
|
120 |
|
121 // reply |
|
122 if ((err = -fuse_reply_readlink(req, link))) |
|
123 EERROR(err, "fuse_reply_readlink"); |
|
124 |
|
125 error: |
|
126 if (err && (err = -fuse_reply_err(req, err))) |
|
127 EWARNING(err, "fuse_reply_err"); |
|
128 |
|
129 // free |
|
130 evsql_result_free(res); |
|
131 } |
|
132 |
|
133 void dbfs_readlink (struct fuse_req *req, fuse_ino_t ino) { |
|
134 struct dbfs *ctx = fuse_req_userdata(req); |
|
135 struct evsql_query *query; |
|
136 int err; |
|
137 |
|
138 INFO("[dbfs.readlink %p] ino=%lu", req, ino); |
|
139 |
|
140 const char *sql = |
|
141 "SELECT" |
|
142 " inodes.ino, inodes.type, inodes.link_path" |
|
143 " FROM inodes" |
|
144 " WHERE inodes.ino = $1::int4"; |
|
145 |
|
146 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
|
147 EVSQL_PARAM ( UINT32 ), |
|
148 |
|
149 EVSQL_PARAMS_END |
|
150 }; |
|
151 |
|
152 // build params |
|
153 if (0 |
|
154 || evsql_param_uint32(¶ms, 0, ino) |
|
155 ) |
|
156 SERROR(err = EIO); |
|
157 |
|
158 // query |
|
159 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, _dbfs_readlink_res, req)) == NULL) |
|
160 SERROR(err = EIO); |
|
161 |
|
162 // handle interrupts |
|
163 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
|
164 |
|
165 // wait |
|
166 return; |
|
167 |
|
168 error: |
|
169 if ((err = -fuse_reply_err(req, err))) |
|
170 EWARNING(err, "fuse_reply_err"); |
|
171 |
|
172 } |
|
173 |
|
174 #define SETERR(err_var, err_val, bool_val) ((err_var) = bool_val ? (err_val) : 0) |
|
175 |
|
176 void dbfs_unlink_res (const struct evsql_result_info *res, void *arg) { |
|
177 struct fuse_req *req = arg; |
|
178 int err = 0; |
|
179 |
|
180 // check the results |
|
181 // XXX: reply with ENOTEMPTY if it fails due to this inode being a dir |
|
182 if ((err = dbfs_check_result(res, 1, 0))) |
|
183 goto error; |
|
184 |
|
185 INFO("\t[dbfs.unlink %p] -> OK", req); |
|
186 |
|
187 // reply |
|
188 if ((err = -fuse_reply_err(req, 0))) |
|
189 EERROR(err, "fuse_reply_err"); |
|
190 |
|
191 error: |
|
192 if (err && (err = -fuse_reply_err(req, err))) |
|
193 EWARNING(err, "fuse_reply_err"); |
|
194 |
|
195 // free |
|
196 evsql_result_free(res); |
|
197 } |
|
198 |
|
199 void dbfs_unlink (struct fuse_req *req, fuse_ino_t parent, const char *name) { |
|
200 struct dbfs *ctx = fuse_req_userdata(req); |
|
201 struct evsql_query *query; |
|
202 int err; |
|
203 |
|
204 INFO("[dbfs.unlink %p] parent=%lu, name=%s", req, parent, name); |
|
205 |
|
206 const char *sql = |
|
207 "DELETE" |
|
208 " FROM file_tree" |
|
209 " WHERE parent = $1::int4 AND name = $2::varchar"; |
|
210 |
|
211 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
|
212 EVSQL_PARAM ( UINT32 ), |
|
213 EVSQL_PARAM ( STRING ), |
|
214 |
|
215 EVSQL_PARAMS_END |
|
216 }; |
|
217 |
|
218 // build params |
|
219 if (0 |
|
220 || evsql_param_uint32(¶ms, 0, parent) |
|
221 || evsql_param_string(¶ms, 1, name) |
|
222 ) |
|
223 SERROR(err = EIO); |
|
224 |
|
225 // query |
|
226 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, dbfs_unlink_res, req)) == NULL) |
|
227 SERROR(err = EIO); |
|
228 |
|
229 // handle interrupts |
|
230 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
|
231 |
|
232 // wait |
|
233 return; |
|
234 |
|
235 error: |
|
236 if ((err = -fuse_reply_err(req, err))) |
|
237 EWARNING(err, "fuse_reply_err"); |
|
238 } |
|
239 |
|
240 void dbfs_link (struct fuse_req *req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) { |
|
241 struct dbfs *ctx = fuse_req_userdata(req); |
|
242 struct evsql_query *query; |
|
243 int err; |
|
244 |
|
245 INFO("[dbfs.link %p] ino=%lu, newparent=%lu, newname=%s", req, ino, newparent, newname); |
|
246 |
|
247 const char *sql = |
|
248 "SELECT ino, type, mode, size, nlink FROM dbfs_link($1::int4, $2::int4, $3::varchar)"; |
|
249 |
|
250 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
|
251 EVSQL_PARAM ( UINT32 ), |
|
252 EVSQL_PARAM ( UINT32 ), |
|
253 EVSQL_PARAM ( STRING ), |
|
254 |
|
255 EVSQL_PARAMS_END |
|
256 }; |
|
257 |
|
258 // build params |
|
259 if (0 |
|
260 || evsql_param_uint32(¶ms, 0, ino) |
|
261 || evsql_param_uint32(¶ms, 1, newparent) |
|
262 || evsql_param_string(¶ms, 2, newname) |
|
263 ) |
|
264 SERROR(err = EIO); |
|
265 |
|
266 // query |
|
267 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, dbfs_entry_res, req)) == NULL) |
|
268 SERROR(err = EIO); |
|
269 |
|
270 // handle interrupts |
|
271 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
|
272 |
|
273 // wait |
|
274 return; |
|
275 |
|
276 error: |
|
277 if ((err = -fuse_reply_err(req, err))) |
|
278 EWARNING(err, "fuse_reply_err"); |
|
279 } |
|