Blob


1 /*
2 * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 #include <sys/uio.h>
21 #include <event.h>
22 #include <ctype.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <imsg.h>
29 #include "kami.h"
30 #include "log.h"
31 #include "utils.h"
33 void *
34 xmalloc(size_t size)
35 {
36 void *r;
38 if ((r = malloc(size)) == NULL)
39 fatal("malloc");
40 return r;
41 }
43 void *
44 xcalloc(size_t nmemb, size_t size)
45 {
46 void *r;
48 if ((r = calloc(nmemb, size)) == NULL)
49 fatal("calloc");
50 return r;
51 }
53 char *
54 xstrdup(const char *s)
55 {
56 char *r;
58 if ((r = strdup(s)) == NULL)
59 fatal("strdup");
60 return r;
61 }
63 void *
64 xmemdup(const void *d, size_t len)
65 {
66 void *r;
68 if ((r = malloc(len)) == NULL)
69 fatal("malloc");
70 memcpy(r, d, len);
71 return r;
72 }
74 const char *
75 pp_msg_type(uint8_t type)
76 {
77 switch (type) {
78 case Tversion: return "Tversion";
79 case Rversion: return "Rversion";
80 case Tauth: return "Tauth";
81 case Rauth: return "Rauth";
82 case Tattach: return "Tattach";
83 case Rattach: return "Rattach";
84 case Terror: return "Terror"; /* illegal */
85 case Rerror: return "Rerror";
86 case Tflush: return "Tflush";
87 case Rflush: return "Rflush";
88 case Twalk: return "Twalk";
89 case Rwalk: return "Rwalk";
90 case Topen: return "Topen";
91 case Ropen: return "Ropen";
92 case Tcreate: return "Tcreate";
93 case Rcreate: return "Rcreate";
94 case Tread: return "Tread";
95 case Rread: return "Rread";
96 case Twrite: return "Twrite";
97 case Rwrite: return "Rwrite";
98 case Tclunk: return "Tclunk";
99 case Rclunk: return "Rclunk";
100 case Tremove: return "Tremove";
101 case Rremove: return "Rremove";
102 case Tstat: return "Tstat";
103 case Rstat: return "Rstat";
104 case Twstat: return "Twstat";
105 case Rwstat: return "Rwstat";
106 default: return "unknown";
110 const char *
111 pp_qid_type(uint8_t type)
113 switch (type) {
114 case QTDIR: return "dir";
115 case QTAPPEND: return "append-only";
116 case QTEXCL: return "exclusive";
117 case QTMOUNT: return "mounted-channel";
118 case QTAUTH: return "authentication";
119 case QTTMP: return "non-backed-up";
120 case QTSYMLINK: return "symlink";
121 case QTFILE: return "file";
124 return "unknown";
127 static void
128 hexdump_ppline(int x, uint8_t *data, size_t len)
130 for (; x < 50; x++)
131 printf(" ");
133 printf("|");
135 for (x = 0; x < (int)len; ++x) {
136 if (isgraph(data[x]))
137 printf("%c", data[x]);
138 else
139 printf(".");
142 printf("|\n");
145 void
146 hexdump(const char *label, uint8_t *data, size_t len)
148 size_t i;
149 int x, n;
151 /*
152 * Layout:
153 * === first block === == second block == |........|\n
154 * first and second block are 8 bytes long (for a total of 48
155 * columns), plus two separator plus two | plus 16 chars, for
156 * a total of 68 characters.
157 */
159 printf("\nhexdump \"%s\": (%zu bytes)\n", label, len);
160 for (x = 0, n = 0, i = 0; i < len; ++i) {
161 if (i != 0 && i % 8 == 0) {
162 printf(" ");
163 x++;
166 if (n == 16) {
167 hexdump_ppline(x, &data[i - 16], 16);
168 x = 0;
169 n = 0;
172 printf("%02x ", data[i]);
173 x += 3;
174 n++;
177 if (n != 0)
178 hexdump_ppline(x, &data[i - n], n);
180 printf("\n");
183 void
184 imsg_event_add(struct imsgev *iev)
186 iev->events = EV_READ;
187 if (iev->ibuf.w.queued)
188 iev->events |= EV_WRITE;
190 event_del(&iev->ev);
191 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
192 event_add(&iev->ev, NULL);
195 int
196 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
197 pid_t pid, int fd, const void *data, uint16_t datalen)
199 int ret;
201 if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data,
202 datalen) != -1))
203 imsg_event_add(iev);
205 return ret;