31
|
1 |
|
|
2 |
#include "dbfs.h"
|
|
3 |
#include "../lib/log.h"
|
|
4 |
#include "../lib/misc.h"
|
|
5 |
|
|
6 |
// max. size for a setattr UPDATE query
|
|
7 |
#define DBFS_SETATTR_SQL_MAX 512
|
|
8 |
|
|
9 |
// for building the setattr UPDATE
|
|
10 |
#define FIELD(to_set, flag, field, value) ((to_set) & (flag)) ? (field " = " value ", ") : ""
|
|
11 |
|
|
12 |
void _dbfs_attr_res (const struct evsql_result_info *res, void *arg) {
|
|
13 |
struct fuse_req *req = arg;
|
|
14 |
struct stat st; ZINIT(st);
|
|
15 |
int err = 0;
|
|
16 |
|
|
17 |
uint32_t ino;
|
|
18 |
|
|
19 |
// check the results
|
|
20 |
if ((err = _dbfs_check_res(res, 1, 5)))
|
|
21 |
SERROR(err = (err == 1 ? ENOENT : EIO));
|
|
22 |
|
|
23 |
// get our data
|
|
24 |
if (0
|
|
25 |
|| evsql_result_uint32(res, 0, 0, &ino, 0 ) // inodes.ino
|
|
26 |
)
|
|
27 |
EERROR(err = EIO, "invalid db data");
|
|
28 |
|
|
29 |
|
|
30 |
INFO("[dbfs.getattr %p] -> ino=%lu, stat follows", req, (unsigned long int) ino);
|
|
31 |
|
|
32 |
// stat attrs
|
|
33 |
if ((err = _dbfs_stat_info(&st, res, 0, 1)))
|
|
34 |
goto error;
|
|
35 |
|
|
36 |
// XXX: we don't have the ino
|
|
37 |
st.st_ino = ino;
|
|
38 |
|
|
39 |
// reply
|
|
40 |
if ((err = fuse_reply_attr(req, &st, st.st_nlink ? CACHE_TIMEOUT : 0)))
|
|
41 |
EERROR(err, "fuse_reply_entry");
|
|
42 |
|
|
43 |
error:
|
|
44 |
if (err && (err = fuse_reply_err(req, err)))
|
|
45 |
EWARNING(err, "fuse_reply_err");
|
|
46 |
|
|
47 |
// free
|
|
48 |
evsql_result_free(res);
|
|
49 |
}
|
|
50 |
|
|
51 |
void dbfs_getattr (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi) {
|
|
52 |
struct dbfs *ctx = fuse_req_userdata(req);
|
|
53 |
int err;
|
|
54 |
|
|
55 |
(void) fi;
|
|
56 |
|
|
57 |
INFO("[dbfs.getattr %p] ino=%lu", req, ino);
|
|
58 |
|
|
59 |
const char *sql =
|
|
60 |
"SELECT"
|
|
61 |
" inodes.ino, " DBFS_STAT_COLS
|
|
62 |
" FROM inodes"
|
|
63 |
" WHERE inodes.ino = $1::int4"
|
|
64 |
" GROUP BY inodes.ino, inodes.type, inodes.mode, data";
|
|
65 |
|
|
66 |
static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
|
|
67 |
EVSQL_PARAM ( UINT32 ),
|
|
68 |
|
|
69 |
EVSQL_PARAMS_END
|
|
70 |
};
|
|
71 |
|
|
72 |
// build params
|
|
73 |
if (0
|
|
74 |
|| evsql_param_uint32(¶ms, 0, ino)
|
|
75 |
)
|
|
76 |
SERROR(err = EIO);
|
|
77 |
|
|
78 |
// query
|
|
79 |
if (evsql_query_params(ctx->db, NULL, sql, ¶ms, _dbfs_attr_res, req) == NULL)
|
|
80 |
SERROR(err = EIO);
|
|
81 |
|
|
82 |
// XXX: handle interrupts
|
|
83 |
|
|
84 |
// wait
|
|
85 |
return;
|
|
86 |
|
|
87 |
error:
|
|
88 |
if ((err = fuse_reply_err(req, err)))
|
|
89 |
EWARNING(err, "fuse_reply_err");
|
|
90 |
}
|
|
91 |
|
|
92 |
|
|
93 |
void dbfs_setattr (struct fuse_req *req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi) {
|
|
94 |
struct dbfs *ctx = fuse_req_userdata(req);
|
|
95 |
int err;
|
|
96 |
int ret;
|
|
97 |
|
|
98 |
char sql_buf[DBFS_SETATTR_SQL_MAX];
|
|
99 |
|
|
100 |
static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
|
|
101 |
EVSQL_PARAM ( UINT16 ), // inodes.mode
|
|
102 |
EVSQL_PARAM ( UINT32 ), // inodes.uid
|
|
103 |
EVSQL_PARAM ( UINT32 ), // inodes.gid
|
|
104 |
EVSQL_PARAM ( UINT32 ), // data size
|
|
105 |
EVSQL_PARAM ( UINT32 ), // ino
|
|
106 |
|
|
107 |
EVSQL_PARAMS_END
|
|
108 |
};
|
|
109 |
|
|
110 |
// log
|
|
111 |
INFO("[dbfs.setattr %p] ino=%lu, fileop=%p: ", req, ino, fi && fi->fh ? (void*) fi->fh : NULL);
|
|
112 |
|
|
113 |
if (to_set & FUSE_SET_ATTR_MODE) {
|
|
114 |
// ignore the S_IFMT
|
|
115 |
attr->st_mode &= 07777;
|
|
116 |
|
|
117 |
INFO("\tmode = %08o", attr->st_mode);
|
|
118 |
}
|
|
119 |
|
|
120 |
if (to_set & FUSE_SET_ATTR_UID)
|
|
121 |
INFO("\tuid = %u", attr->st_uid);
|
|
122 |
|
|
123 |
if (to_set & FUSE_SET_ATTR_GID)
|
|
124 |
INFO("\tgid = %u", attr->st_gid);
|
|
125 |
|
|
126 |
if (to_set & FUSE_SET_ATTR_SIZE)
|
|
127 |
INFO("\tsize = %lu", attr->st_size);
|
|
128 |
|
|
129 |
if (to_set & FUSE_SET_ATTR_ATIME)
|
|
130 |
INFO("\tatime = %lu", attr->st_atime);
|
|
131 |
|
|
132 |
if (to_set & FUSE_SET_ATTR_MTIME)
|
|
133 |
INFO("\tmtime = %lu", attr->st_mtime);
|
|
134 |
|
|
135 |
// the SQL
|
|
136 |
if ((ret = snprintf(sql_buf, DBFS_SETATTR_SQL_MAX,
|
|
137 |
"UPDATE inodes SET"
|
|
138 |
" %s%s%s%s ino = ino"
|
|
139 |
" WHERE inodes.ino = $5::int4"
|
|
140 |
" RETURNING inodes.ino, " DBFS_STAT_COLS_NOAGGREGATE,
|
|
141 |
|
|
142 |
FIELD(to_set, FUSE_SET_ATTR_MODE, "mode", "$1::int2"),
|
|
143 |
FIELD(to_set, FUSE_SET_ATTR_UID, "uid", "$2::int4"),
|
|
144 |
FIELD(to_set, FUSE_SET_ATTR_GID, "gid", "$3::int4"),
|
|
145 |
FIELD(to_set, FUSE_SET_ATTR_SIZE, "data", "lo_otruncate(data, $4::int4)")
|
|
146 |
)) >= DBFS_SETATTR_SQL_MAX && (err = EIO))
|
|
147 |
ERROR("sql_buf is too small: %i", ret);
|
|
148 |
|
|
149 |
// the params...
|
|
150 |
if (0
|
|
151 |
|| ( evsql_params_clear(¶ms) )
|
|
152 |
|| ((to_set & FUSE_SET_ATTR_MODE ) && evsql_param_uint16(¶ms, 0, attr->st_mode) )
|
|
153 |
|| ((to_set & FUSE_SET_ATTR_UID ) && evsql_param_uint32(¶ms, 1, attr->st_uid) )
|
|
154 |
|| ((to_set & FUSE_SET_ATTR_GID ) && evsql_param_uint32(¶ms, 2, attr->st_gid) )
|
|
155 |
|| ((to_set & FUSE_SET_ATTR_SIZE ) && evsql_param_uint32(¶ms, 3, attr->st_size) )
|
|
156 |
|| ( evsql_param_uint32(¶ms, 4, ino) )
|
|
157 |
)
|
|
158 |
SERROR(err = EIO);
|
|
159 |
|
|
160 |
// trace the query
|
|
161 |
evsql_query_debug(sql_buf, ¶ms);
|
|
162 |
|
|
163 |
// query... we can pretend it's a getattr :)
|
|
164 |
if (evsql_query_params(ctx->db, NULL, sql_buf, ¶ms, _dbfs_attr_res, req) == NULL)
|
|
165 |
SERROR(err = EIO);
|
|
166 |
|
|
167 |
// XXX: handle interrupts
|
|
168 |
|
|
169 |
// wait
|
|
170 |
return;
|
|
171 |
|
|
172 |
error:
|
|
173 |
if ((err = fuse_reply_err(req, err)))
|
|
174 |
EWARNING(err, "fuse_reply_err");
|
|
175 |
}
|