62 struct dbfs *ctx = fuse_req_userdata(req); |
62 struct dbfs *ctx = fuse_req_userdata(req); |
63 struct evsql_query *query; |
63 struct evsql_query *query; |
64 int err; |
64 int err; |
65 |
65 |
66 INFO("[dbfs.lookup] parent=%lu name=%s", parent, name); |
66 INFO("[dbfs.lookup] parent=%lu name=%s", parent, name); |
67 |
67 |
68 // query and params |
68 // query info |
69 const char *sql = |
69 static struct evsql_query_info query_info = { |
70 "SELECT" |
70 .sql = "SELECT" |
71 " inodes.ino, " DBFS_STAT_COLS |
71 " inodes.ino, " DBFS_STAT_COLS |
72 " FROM file_tree INNER JOIN inodes ON (file_tree.ino = inodes.ino)" |
72 " FROM file_tree INNER JOIN inodes ON (file_tree.ino = inodes.ino)" |
73 " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar"; |
73 " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar", |
74 |
74 |
75 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
75 .params = { |
76 EVSQL_PARAM ( UINT32 ), |
76 EVSQL_TYPE ( UINT32 ), |
77 EVSQL_PARAM ( STRING ), |
77 EVSQL_TYPE ( STRING ), |
78 |
78 |
79 EVSQL_PARAMS_END |
79 EVSQL_TYPE_END |
80 }; |
80 } |
81 |
81 }; |
82 // build params |
82 |
83 if (0 |
83 // query |
84 || evsql_param_uint32(¶ms, 0, parent) |
84 if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_entry_res, req, |
85 || evsql_param_string(¶ms, 1, name) |
85 (uint32_t) parent, |
86 ) |
86 (const char *) name |
87 EERROR(err = EIO, "evsql_param_*"); |
87 )) == NULL) |
88 |
|
89 // query |
|
90 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, dbfs_entry_res, req)) == NULL) |
|
91 EERROR(err = EIO, "evsql_query_params"); |
88 EERROR(err = EIO, "evsql_query_params"); |
92 |
89 |
93 // handle interrupts |
90 // handle interrupts |
94 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
91 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
95 |
92 |
99 error: |
96 error: |
100 if ((err = -fuse_reply_err(req, err))) |
97 if ((err = -fuse_reply_err(req, err))) |
101 EWARNING(err, "fuse_reply_err"); |
98 EWARNING(err, "fuse_reply_err"); |
102 } |
99 } |
103 |
100 |
104 void _dbfs_readlink_res (struct evsql_result *res, void *arg) { |
101 void dbfs_readlink_res (struct evsql_result *res, void *arg) { |
105 struct fuse_req *req = arg; |
102 struct fuse_req *req = arg; |
106 int err = 0; |
103 int err = 0; |
107 |
104 |
108 uint32_t ino; |
105 uint32_t ino; |
109 const char *type, *link; |
106 const char *type, *link; |
110 |
107 |
111 // check the results |
108 // result info |
112 if ((err = _dbfs_check_res(res, 1, 3))) |
109 static struct evsql_result_info result_info = { |
113 SERROR(err = (err == 1 ? ENOENT : EIO)); |
110 0, { |
114 |
111 EVSQL_TYPE ( UINT32 ), |
115 // get our data |
112 EVSQL_TYPE ( STRING ), |
116 if (0 |
113 EVSQL_TYPE ( STRING ), |
117 || evsql_result_uint32(res, 0, 0, &ino, 0 ) // inodes.ino |
114 |
118 || evsql_result_string(res, 0, 1, &type, 0 ) // inodes.type |
115 EVSQL_TYPE_END |
119 || evsql_result_string(res, 0, 2, &link, 1 ) // inodes.link_path |
116 } |
120 ) |
117 }; |
121 EERROR(err = EIO, "invalid db data"); |
118 |
|
119 // begin |
|
120 if ((err = evsql_result_begin(&result_info, res))) |
|
121 EERROR(err, "evsql_result_begin"); |
|
122 |
|
123 // get the row of data |
|
124 if ((err = evsql_result_next(res, |
|
125 &ino, &type, &link |
|
126 )) <= 0) |
|
127 SERROR(err = err || ENOENT); |
122 |
128 |
123 // is it a symlink? |
129 // is it a symlink? |
124 if (_dbfs_mode(type) != S_IFLNK) |
130 if (_dbfs_mode(type) != S_IFLNK) |
125 EERROR(err = EINVAL, "wrong type: %s", type); |
131 EERROR(err = EINVAL, "wrong type: %s", type); |
126 |
132 |
142 struct dbfs *ctx = fuse_req_userdata(req); |
148 struct dbfs *ctx = fuse_req_userdata(req); |
143 struct evsql_query *query; |
149 struct evsql_query *query; |
144 int err; |
150 int err; |
145 |
151 |
146 INFO("[dbfs.readlink %p] ino=%lu", req, ino); |
152 INFO("[dbfs.readlink %p] ino=%lu", req, ino); |
147 |
153 |
148 const char *sql = |
154 // query info |
149 "SELECT" |
155 static struct evsql_query_info query_info = { |
150 " inodes.ino, inodes.type, inodes.link_path" |
156 .sql = "SELECT" |
151 " FROM inodes" |
157 " inodes.ino, inodes.type, inodes.link_path" |
152 " WHERE inodes.ino = $1::int4"; |
158 " FROM inodes" |
153 |
159 " WHERE inodes.ino = $1::int4", |
154 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
160 |
155 EVSQL_PARAM ( UINT32 ), |
161 .params = { |
156 |
162 EVSQL_TYPE ( UINT32 ), |
157 EVSQL_PARAMS_END |
163 |
158 }; |
164 EVSQL_TYPE_END |
159 |
165 } |
160 // build params |
166 }; |
161 if (0 |
167 |
162 || evsql_param_uint32(¶ms, 0, ino) |
168 // query |
163 ) |
169 if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_readlink_res, req, |
|
170 (uint32_t) ino |
|
171 )) == NULL) |
164 SERROR(err = EIO); |
172 SERROR(err = EIO); |
165 |
173 |
166 // query |
174 // handle interrupts |
167 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, _dbfs_readlink_res, req)) == NULL) |
175 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
168 SERROR(err = EIO); |
176 |
169 |
177 // wait |
170 // handle interrupts |
178 return; |
171 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
179 |
172 |
180 error: |
173 // wait |
181 if ((err = -fuse_reply_err(req, err))) |
174 return; |
182 EWARNING(err, "fuse_reply_err"); |
175 |
183 |
176 error: |
184 } |
177 if ((err = -fuse_reply_err(req, err))) |
|
178 EWARNING(err, "fuse_reply_err"); |
|
179 |
|
180 } |
|
181 |
|
182 #define SETERR(err_var, err_val, bool_val) ((err_var) = bool_val ? (err_val) : 0) |
|
183 |
185 |
184 void dbfs_unlink_res (struct evsql_result *res, void *arg) { |
186 void dbfs_unlink_res (struct evsql_result *res, void *arg) { |
185 struct fuse_req *req = arg; |
187 struct fuse_req *req = arg; |
186 int err = 0; |
188 int err = 0; |
187 |
189 |
188 // check the results |
190 // check |
189 // XXX: reply with ENOTEMPTY if it fails due to this inode being a dir |
191 if ((err = evsql_result_check(res))) |
190 if ((err = dbfs_check_result(res, 1, 0))) |
192 ERROR("evsql_result_check: %s", evsql_result_error(res)); |
191 goto error; |
193 |
192 |
|
193 INFO("\t[dbfs.unlink %p] -> OK", req); |
194 INFO("\t[dbfs.unlink %p] -> OK", req); |
194 |
195 |
195 // reply |
196 // reply |
196 if ((err = -fuse_reply_err(req, 0))) |
197 if ((err = -fuse_reply_err(req, 0))) |
197 EERROR(err, "fuse_reply_err"); |
198 EERROR(err, "fuse_reply_err"); |
208 struct dbfs *ctx = fuse_req_userdata(req); |
209 struct dbfs *ctx = fuse_req_userdata(req); |
209 struct evsql_query *query; |
210 struct evsql_query *query; |
210 int err; |
211 int err; |
211 |
212 |
212 INFO("[dbfs.unlink %p] parent=%lu, name=%s", req, parent, name); |
213 INFO("[dbfs.unlink %p] parent=%lu, name=%s", req, parent, name); |
213 |
214 |
214 const char *sql = |
215 // query info |
215 "DELETE" |
216 static struct evsql_query_info query_info = { |
216 " FROM file_tree" |
217 .sql = "DELETE" |
217 " WHERE parent = $1::int4 AND name = $2::varchar"; |
218 " FROM file_tree" |
218 |
219 " WHERE parent = $1::int4 AND name = $2::varchar", |
219 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
220 |
220 EVSQL_PARAM ( UINT32 ), |
221 .params = { |
221 EVSQL_PARAM ( STRING ), |
222 EVSQL_TYPE ( UINT32 ), |
222 |
223 EVSQL_TYPE ( STRING ), |
223 EVSQL_PARAMS_END |
224 |
224 }; |
225 EVSQL_TYPE_END |
225 |
226 } |
226 // build params |
227 }; |
227 if (0 |
228 |
228 || evsql_param_uint32(¶ms, 0, parent) |
229 // query |
229 || evsql_param_string(¶ms, 1, name) |
230 if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_unlink_res, req, |
230 ) |
231 (uint32_t) parent, |
|
232 (const char *) name |
|
233 )) == NULL) |
231 SERROR(err = EIO); |
234 SERROR(err = EIO); |
232 |
235 |
233 // query |
236 // handle interrupts |
234 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, dbfs_unlink_res, req)) == NULL) |
237 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
|
238 |
|
239 // wait |
|
240 return; |
|
241 |
|
242 error: |
|
243 if ((err = -fuse_reply_err(req, err))) |
|
244 EWARNING(err, "fuse_reply_err"); |
|
245 } |
|
246 |
|
247 void dbfs_link (struct fuse_req *req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) { |
|
248 struct dbfs *ctx = fuse_req_userdata(req); |
|
249 struct evsql_query *query; |
|
250 int err; |
|
251 |
|
252 INFO("[dbfs.link %p] ino=%lu, newparent=%lu, newname=%s", req, ino, newparent, newname); |
|
253 |
|
254 // query info |
|
255 static struct evsql_query_info query_info = { |
|
256 .sql = "SELECT ino, type, mode, size, nlink FROM dbfs_link($1::int4, $2::int4, $3::varchar)", |
|
257 |
|
258 .params = { |
|
259 EVSQL_TYPE ( UINT32 ), |
|
260 EVSQL_TYPE ( UINT32 ), |
|
261 EVSQL_TYPE ( STRING ), |
|
262 |
|
263 EVSQL_TYPE_END |
|
264 } |
|
265 }; |
|
266 |
|
267 // query |
|
268 if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_entry_res, req, |
|
269 (uint32_t) ino, |
|
270 (uint32_t) newparent, |
|
271 (const char *) newname |
|
272 )) == NULL) |
235 SERROR(err = EIO); |
273 SERROR(err = EIO); |
236 |
274 |
237 // handle interrupts |
275 // handle interrupts |
238 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
276 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
239 |
277 |
240 // wait |
278 // wait |
241 return; |
279 return; |
242 |
280 |
243 error: |
281 error: |
244 if ((err = -fuse_reply_err(req, err))) |
282 if ((err = -fuse_reply_err(req, err))) |
245 EWARNING(err, "fuse_reply_err"); |
|
246 } |
|
247 |
|
248 void dbfs_link (struct fuse_req *req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) { |
|
249 struct dbfs *ctx = fuse_req_userdata(req); |
|
250 struct evsql_query *query; |
|
251 int err; |
|
252 |
|
253 INFO("[dbfs.link %p] ino=%lu, newparent=%lu, newname=%s", req, ino, newparent, newname); |
|
254 |
|
255 const char *sql = |
|
256 "SELECT ino, type, mode, size, nlink FROM dbfs_link($1::int4, $2::int4, $3::varchar)"; |
|
257 |
|
258 static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { |
|
259 EVSQL_PARAM ( UINT32 ), |
|
260 EVSQL_PARAM ( UINT32 ), |
|
261 EVSQL_PARAM ( STRING ), |
|
262 |
|
263 EVSQL_PARAMS_END |
|
264 }; |
|
265 |
|
266 // build params |
|
267 if (0 |
|
268 || evsql_param_uint32(¶ms, 0, ino) |
|
269 || evsql_param_uint32(¶ms, 1, newparent) |
|
270 || evsql_param_string(¶ms, 2, newname) |
|
271 ) |
|
272 SERROR(err = EIO); |
|
273 |
|
274 // query |
|
275 if ((query = evsql_query_params(ctx->db, NULL, sql, ¶ms, dbfs_entry_res, req)) == NULL) |
|
276 SERROR(err = EIO); |
|
277 |
|
278 // handle interrupts |
|
279 fuse_req_interrupt_func(req, dbfs_interrupt_query, query); |
|
280 |
|
281 // wait |
|
282 return; |
|
283 |
|
284 error: |
|
285 if ((err = -fuse_reply_err(req, err))) |
|
286 EWARNING(err, "fuse_reply_err"); |
283 EWARNING(err, "fuse_reply_err"); |
287 } |
284 } |
|
285 |