cmogstored 1.8.1 - use default system stack size
[cmogstored.git] / mgmt_fn.c
blobc08e0b85294b147345c5506b9875fef956c57a39
1 /*
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>
4 */
5 #include "cmogstored.h"
6 #include "mgmt.h"
7 #include "iov_str.h"
8 #include "digest.h"
10 static char *
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)) {
17 char *path;
19 if (sdup) {
20 path = malloc(dst->iov_len + 1);
21 if (!path) {
22 struct iovec iov;
24 IOV_STR(&iov, "ERROR: out-of-memory\r\n");
25 mog_mgmt_writev(mgmt, &iov, 1);
27 return NULL;
30 memcpy(path, dst->iov_base, dst->iov_len);
31 } else {
32 path = dst->iov_base;
35 path[dst->iov_len] = '\0';
36 return path;
37 } else {
38 struct iovec iov;
40 IOV_STR(&iov, "ERROR: uri invalid (contains ..)\r\n");
41 mog_mgmt_writev(mgmt, &iov, 1);
42 return NULL;
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;
50 struct iovec iov[2];
51 char *path = get_path(iov, mgmt, buf, true);
53 if (!path) return;
55 TRACE(CMOGSTORED_MGMT_DIG_START(mfd->fd, mgmt->alg, path));
57 mgmt->forward = mog_file_open_read(mgmt->svc, path);
58 if (mgmt->forward) {
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;
65 file->path = path;
66 } else {
67 switch (mgmt->alg) {
68 case GC_MD5:
69 IOV_STR(&iov[1], " MD5=-1\r\n");
70 break;
71 case GC_SHA1:
72 IOV_STR(&iov[1], " SHA-1=-1\r\n");
73 break;
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);
79 free(path);
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;
89 struct iovec iov[3];
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;
111 struct iovec iov[2];
112 char buf[CLEN(" SHA-1=") + 40 + CLEN("\r\n")];
113 char *b = buf;
114 struct mog_fd *file_mfd = mgmt->forward;
115 struct mog_file *file = &file_mfd->as.file;
116 size_t len;
118 iov[0].iov_base = file->path;
119 iov[0].iov_len = file->pathlen;
121 /* ugh, clean this up... */
122 switch (mgmt->alg) {
123 case GC_MD5:
124 b = mempcpy(b, " MD5=", CLEN(" MD5="));
125 len = 32;
126 iov[1].iov_len = CLEN(" MD5=") + 32 + CLEN("\r\n");
127 break;
128 case GC_SHA1:
129 b = mempcpy(b, " SHA-1=", CLEN(" SHA-1="));
130 len = 40;
131 iov[1].iov_len = sizeof(buf);
132 break;
133 default:
134 die("BUG: unhandled algorithm: %d", mgmt->alg);
137 mog_digest_hex(&file->digest, b, len);
138 b[len] = '\r';
139 b[len + 1] = '\n';
140 iov[1].iov_base = buf;
141 TRACE(CMOGSTORED_MGMT_DIG_DONE(mfd->fd, 0));
142 mog_mgmt_writev(mgmt, iov, 2);
146 * writes to mgmt fd:
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)
153 struct stat sb;
154 struct iovec iov[2];
155 char tmp[sizeof(" 18446744073709551615\r\n") - 1];
156 char *path = get_path(iov, mgmt, buf, false);
158 if (!path) return;
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);
165 } else {
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)
174 struct iovec iov;
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)
182 struct iovec iov[3];
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)
193 struct iovec iov;
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)
201 char *end;
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");
207 *eor = 0;
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);