2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
5 #include "cmogstored.h"
11 get_path(struct iovec
*dst
, struct mog_mgmt
*mgmt
, char *buf
, bool sdup
)
13 dst
->iov_base
= buf
+ mgmt
->mark
[0];
14 dst
->iov_len
= mgmt
->mark
[1] - mgmt
->mark
[0];
16 if (mog_valid_path(dst
->iov_base
, dst
->iov_len
)) {
20 path
= malloc(dst
->iov_len
+ 1);
24 IOV_STR(&iov
, "ERROR: out-of-memory\r\n");
25 mog_mgmt_writev(mgmt
, &iov
, 1);
30 memcpy(path
, dst
->iov_base
, dst
->iov_len
);
35 path
[dst
->iov_len
] = '\0';
40 IOV_STR(&iov
, "ERROR: uri invalid (contains ..)\r\n");
41 mog_mgmt_writev(mgmt
, &iov
, 1);
46 /* starts the MD5 request */
47 void mog_mgmt_fn_digest(struct mog_fd
*mfd
, char *buf
)
49 struct mog_mgmt
*mgmt
= &mfd
->as
.mgmt
;
51 char *path
= get_path(iov
, mgmt
, buf
, true);
55 TRACE(CMOGSTORED_MGMT_DIG_START(mfd
->fd
, mgmt
->alg
, path
));
57 mgmt
->forward
= mog_file_open_read(mgmt
->svc
, path
);
59 struct mog_file
*file
= &mgmt
->forward
->as
.file
;
61 mog_fadv_noreuse(mgmt
->forward
->fd
, 0, 0 /* ALL */);
62 mog_fadv_sequential(mgmt
->forward
->fd
, 0, 0 /* ALL */);
63 mog_digest_init(&file
->digest
, mgmt
->alg
);
64 file
->pathlen
= iov
[0].iov_len
;
69 IOV_STR(&iov
[1], " MD5=-1\r\n");
72 IOV_STR(&iov
[1], " SHA-1=-1\r\n");
74 default: /* Ragel parser prevents this: */
75 die("BUG: unhandled algorithm: %d", mgmt
->alg
);
77 TRACE(CMOGSTORED_MGMT_DIG_DONE(mfd
->fd
, -1));
78 mog_mgmt_writev(mgmt
, iov
, 2);
83 /* finishes the MD5 request */
84 #define CLEN(s) (sizeof(s)-1)
86 void mog_mgmt_fn_digest_err(struct mog_fd
*mfd
)
88 struct mog_mgmt
*mgmt
= &mfd
->as
.mgmt
;
90 struct mog_fd
*file_mfd
= mgmt
->forward
;
91 struct mog_file
*file
= &file_mfd
->as
.file
;
92 long long offset
= (long long)lseek(file_mfd
->fd
, 0, SEEK_CUR
);
93 char buf
[sizeof(" at 18446744073709551615 failed\r\n") - 1];
95 /* offset could be -1 here, but there ain't much we can do */
97 IOV_STR(iov
, "ERR read ");
98 iov
[1].iov_base
= file
->path
;
99 iov
[1].iov_len
= file
->pathlen
;
100 iov
[2].iov_base
= buf
;
101 iov
[2].iov_len
= snprintf(buf
, sizeof(buf
),
102 " at %lld failed\r\n", offset
);
103 TRACE(CMOGSTORED_MGMT_DIG_DONE(mfd
->fd
, offset
));
104 mog_mgmt_writev(mgmt
, iov
, 3);
107 /* output: "/$PATH MD5=hex\r\n" */
108 void mog_mgmt_fn_digest_emit(struct mog_fd
*mfd
)
110 struct mog_mgmt
*mgmt
= &mfd
->as
.mgmt
;
112 char buf
[CLEN(" SHA-1=") + 40 + CLEN("\r\n")];
114 struct mog_fd
*file_mfd
= mgmt
->forward
;
115 struct mog_file
*file
= &file_mfd
->as
.file
;
118 iov
[0].iov_base
= file
->path
;
119 iov
[0].iov_len
= file
->pathlen
;
121 /* ugh, clean this up... */
124 b
= mempcpy(b
, " MD5=", CLEN(" MD5="));
126 iov
[1].iov_len
= CLEN(" MD5=") + 32 + CLEN("\r\n");
129 b
= mempcpy(b
, " SHA-1=", CLEN(" SHA-1="));
131 iov
[1].iov_len
= sizeof(buf
);
134 die("BUG: unhandled algorithm: %d", mgmt
->alg
);
137 mog_digest_hex(&file
->digest
, b
, len
);
140 iov
[1].iov_base
= buf
;
141 TRACE(CMOGSTORED_MGMT_DIG_DONE(mfd
->fd
, 0));
142 mog_mgmt_writev(mgmt
, iov
, 2);
147 * "URI $SIZE\r\n" on success
148 * "URI -1\r\n" on failure
149 * "ERROR: uri invalid (contains ..)\r\n" on invalid paths
151 void mog_mgmt_fn_size(struct mog_mgmt
*mgmt
, char *buf
)
155 char tmp
[sizeof(" 18446744073709551615\r\n") - 1];
156 char *path
= get_path(iov
, mgmt
, buf
, false);
160 if (mog_stat(mgmt
->svc
, path
, &sb
) == 0) {
161 long long size
= (long long)sb
.st_size
;
163 iov
[1].iov_base
= tmp
;
164 iov
[1].iov_len
= snprintf(tmp
, sizeof(tmp
), " %lld\r\n", size
);
166 IOV_STR(&iov
[1], " -1\r\n");
169 mog_mgmt_writev(mgmt
, iov
, 2);
172 void mog_mgmt_fn_blank(struct mog_mgmt
*mgmt
)
176 IOV_STR(&iov
, "\r\n");
177 mog_mgmt_writev(mgmt
, &iov
, 1);
180 void mog_mgmt_fn_unknown(struct mog_mgmt
*mgmt
, char *buf
)
184 IOV_STR(&iov
[0], "ERROR: unknown command: ");
185 iov
[1].iov_base
= mgmt
->mark
[0] + buf
;
186 iov
[1].iov_len
= mgmt
->mark
[1] - mgmt
->mark
[0];
187 IOV_STR(&iov
[2], "\r\n");
188 mog_mgmt_writev(mgmt
, iov
, 3);
191 void mog_mgmt_fn_watch_err(struct mog_mgmt
*mgmt
)
195 IOV_STR(&iov
, "ERR iostat unavailable\r\n");
196 mog_mgmt_writev(mgmt
, &iov
, 1);
199 void mog_mgmt_fn_aio_threads(struct mog_mgmt
*mgmt
, char *buf
)
202 unsigned long long nr
;
203 char *nptr
= buf
+ mgmt
->mark
[0];
204 char *eor
= nptr
+ mgmt
->mark
[1] - mgmt
->mark
[0];
206 assert((*eor
== '\n' || *eor
== '\r') && "missing end-of-record");
209 nr
= strtoull(nptr
, &end
, 10);
210 assert(*end
== 0 && "ragel misfed mog_mgmt_fn_set_aio_threads");
212 if (nr
> 0 && nr
<= (size_t)INT_MAX
)
213 mog_svc_aio_threads_enqueue(mgmt
->svc
, (unsigned)nr
);
215 mog_mgmt_fn_blank(mgmt
);