History

wip revamping

Sigrid Solveig Haflínudóttir committed 4 years ago

Commit e5e39ad1 parent aa98d289 files · +676 −66Browse files

Unified · Split

9 files
  1. README.md +21 −4
  2. examples/dial.c +50 −0
  3. examples/fs9ptest.c +52 −0
  4. examples/sockets.c +127 −0
  5. fs9p.c +301 −0
  6. include/c9/fs.h +48 −0
  7. include/c9/fs9p.h +31 −0
  8. include/c9/proto.h +6 −10
  9. proto.c +40 −52
README.md+21−4
@@ -1,8 +1,25 @@
11 # c9
22
3−Low level 9p client and server.
3+NOTE (2022-06-27): the library's (yep, it's going to be a library)
4+API is getting completely revamped, and examples are being added.
5+Use either an older version, or expect API breakage.
46
5−## Examples
7+A lightweight library for implmeneting 9p clients and servers in C.
68
7−Until I have time to write a minimal example you could take a look at
8−https://git.sr.ht/~ft/9pro/blob/master/9pex.c
9+This is 9p client and server implementation which aims to be correct,
10+small and secure, targetting mainly low-resource MCUs.
11+
12+`proto.[ch]`: lowest level of the library, contains nothing but
13+(de)serealization of the protocol messages and tag (de)allocation.
14+
15+`fs.h`: higher level, blocking file API based on POSIX.
16+
17+`fs9p.[ch]`: blocking file API implementation for 9p - having a
18+context created with `proto.[ch]` one can use POSIX-like file API to
19+work with a remote filesystem.
20+
21+Goals:
22+
23+* portability: zero external dependencies, no POSIX, just C
24+* no dynamic memory allocation
25+* security: no crashes due to incoming data
examples/dial.c+50−0
@@ -0,0 +1,50 @@
1+#include <string.h>
2+#include <stdio.h>
3+#include <sys/types.h>
4+#include <sys/socket.h>
5+#include <netdb.h>
6+#include <unistd.h>
7+
8+int
9+dial(const char *s)
10+{
11+ struct addrinfo *r, *a, hint = {.ai_flags = AI_ADDRCONFIG, .ai_family = AF_UNSPEC, 0};
12+ char host[128], *port;
13+ int e, f;
14+
15+ if(strncmp(s, "udp!", 4) == 0){
16+ hint.ai_socktype = SOCK_DGRAM;
17+ hint.ai_protocol = IPPROTO_UDP;
18+ }else if(strncmp(s, "tcp!", 4) == 0){
19+ hint.ai_socktype = SOCK_STREAM;
20+ hint.ai_protocol = IPPROTO_TCP;
21+ }else{
22+ fprintf(stderr, "invalid dial string: %s\n", s);
23+ return -1;
24+ }
25+ if((port = strchr(s+4, '!')) == NULL){
26+ fprintf(stderr, "invalid dial string: %s\n", s);
27+ return -1;
28+ }
29+ if(snprintf(host, sizeof(host), "%.*s", (int)(port-s-4), s+4) >= (int)sizeof(host)){
30+ fprintf(stderr, "host name too large: %s\n", s);
31+ return -1;
32+ }
33+ port++;
34+ if((e = getaddrinfo(host, port, &hint, &r)) != 0){
35+ fprintf(stderr, "%s: %s\n", gai_strerror(e), s);
36+ return -1;
37+ }
38+ f = -1;
39+ for(a = r; a != NULL; a = a->ai_next){
40+ if((f = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) < 0)
41+ continue;
42+ if(connect(f, a->ai_addr, a->ai_addrlen) == 0)
43+ break;
44+ close(f);
45+ f = -1;
46+ }
47+ freeaddrinfo(r);
48+
49+ return f;
50+}
examples/fs9ptest.c+52−0
@@ -0,0 +1,52 @@
1+#include <stdio.h>
2+#include <stdint.h>
3+#include <stdarg.h>
4+#include "c9/proto.h"
5+#include "c9/fs.h"
6+#include "c9/fs9p.h"
7+
8+int dial(const char *s);
9+C9ctx *init9p(int f);
10+
11+static FS9pfd fds[8];
12+
13+static void
14+fserror(FS *fs, const char *fmt, ...)
15+{
16+ va_list ap;
17+
18+ (void)fs;
19+ va_start(ap, fmt);
20+ vfprintf(stderr, fmt, ap);
21+ fprintf(stderr, "\n");
22+ va_end(ap);
23+}
24+
25+int
26+main(int argc, char **argv)
27+{
28+ C9ctx *ctx;
29+ FSstat st;
30+ FS fs;
31+ FS9p fs9 = {
32+ .fds = fds,
33+ .numfds = sizeof(fds)/sizeof(fds[0]),
34+ };
35+ int f;
36+
37+ (void)argc; (void)argv;
38+
39+ fs.error = fserror;
40+ fs.aux = (void*)&fs9;
41+ if((f = dial("tcp!ftrv.se!564")) < 0)
42+ return 1;
43+ ctx = init9p(f);
44+ fs9.ctx = ctx;
45+ if(fs9pinit(&fs, 8192) != 0)
46+ return 1;
47+ if(fs.fstat(&fs, FS9proot, &st) != 0)
48+ return 1;
49+ printf("%s %d %s %o\n", st.name, (int)st.size, st.uid, st.mode&0777);
50+
51+ return 0;
52+}
examples/sockets.c+127−0
@@ -0,0 +1,127 @@
1+#include <stdio.h>
2+#include <stdint.h>
3+#include <stdarg.h>
4+#include <errno.h>
5+#include <unistd.h>
6+#include <stdlib.h>
7+#include "c9/proto.h"
8+
9+enum {
10+ Msize = 8192,
11+
12+ Disconnected = 1<<0,
13+};
14+
15+typedef struct C9aux C9aux;
16+
17+struct C9aux {
18+ C9ctx c;
19+ int f;
20+ int flags;
21+ uint8_t rdbuf[Msize];
22+ uint8_t wrbuf[Msize];
23+ uint32_t wroff;
24+};
25+
26+static uint8_t *
27+ctxread(C9ctx *ctx, uint32_t size, int *err)
28+{
29+ uint32_t n;
30+ int r;
31+ C9aux *a;
32+
33+ a = ctx->aux;
34+ *err = 0;
35+ for(n = 0; n < size; n += r){
36+ if((r = read(a->f, a->rdbuf+n, size-n)) <= 0){
37+ if(errno == EINTR)
38+ continue;
39+ a->flags |= Disconnected;
40+ close(a->f);
41+ return NULL;
42+ }
43+ }
44+
45+ return a->rdbuf;
46+}
47+
48+static int
49+wrsend(C9aux *a)
50+{
51+ uint32_t n;
52+ int w;
53+
54+ for(n = 0; n < a->wroff; n += w){
55+ if((w = write(a->f, a->wrbuf+n, a->wroff-n)) <= 0){
56+ if(errno == EINTR)
57+ continue;
58+ if(errno != EPIPE) /* remote end closed */
59+ perror("write");
60+ return -1;
61+ }
62+ }
63+ a->wroff = 0;
64+
65+ return 0;
66+}
67+
68+static uint8_t *
69+ctxbegin(C9ctx *ctx, uint32_t size)
70+{
71+ uint8_t *b;
72+ C9aux *a;
73+
74+ a = ctx->aux;
75+ if(a->wroff + size > sizeof(a->wrbuf)){
76+ if(wrsend(a) != 0 || a->wroff + size > sizeof(a->wrbuf))
77+ return NULL;
78+ }
79+ b = a->wrbuf + a->wroff;
80+ a->wroff += size;
81+
82+ return b;
83+}
84+
85+static int
86+ctxend(C9ctx *ctx)
87+{
88+ C9aux *a;
89+
90+ /*
91+ * To batch up requests and instead flush them all at once just return 0
92+ * here and call wrsend yourself when needed.
93+ */
94+ a = ctx->aux;
95+ return wrsend(a);
96+}
97+
98+static void
99+ctxerror(C9ctx *ctx, const char *fmt, ...)
100+{
101+ va_list ap;
102+
103+ (void)ctx;
104+ va_start(ap, fmt);
105+ vfprintf(stderr, fmt, ap);
106+ fprintf(stderr, "\n");
107+ va_end(ap);
108+}
109+
110+C9aux *
111+init9p(int f)
112+{
113+ C9aux *c;
114+
115+ if((c = calloc(1, sizeof(*c))) == NULL){
116+ close(f);
117+ return NULL;
118+ }
119+ c->f = f;
120+ c->c.read = ctxread;
121+ c->c.begin = ctxbegin;
122+ c->c.end = ctxend;
123+ c->c.error = ctxerror;
124+ c->c.aux = c;
125+
126+ return c;
127+}
fs9p.c+301−0
@@ -0,0 +1,301 @@
1+#include <stdint.h>
2+#include <string.h>
3+#include "c9/proto.h"
4+#include "c9/fs.h"
5+#include "c9/fs9p.h"
6+
7+enum
8+{
9+ Flinit = 1<<0,
10+ Flerror = 1<<1,
11+
12+ F9init = 0,
13+ F9chdir,
14+ F9open,
15+ F9create,
16+ F9read,
17+ F9readdir,
18+ F9write,
19+ F9seek,
20+ F9stat,
21+ F9fstat,
22+ F9close,
23+ F9remove,
24+ F9rename,
25+};
26+
27+static const FS9pfd freefd =
28+{
29+ .offset = ~0ULL,
30+};
31+
32+#define isfree(fd) ((fd).offset == ~0ULL)
33+
34+static const char *f2s[] =
35+{
36+ [F9init] = "init",
37+ [F9chdir] = "chdir",
38+ [F9open] = "open",
39+ [F9create] = "create",
40+ [F9read] = "read",
41+ [F9readdir] = "readdir",
42+ [F9write] = "write",
43+ [F9seek] = "seek",
44+ [F9stat] = "stat",
45+ [F9fstat] = "fstat",
46+ [F9close] = "close",
47+ [F9remove] = "remove",
48+ [F9rename] = "rename",
49+};
50+
51+static int
52+fs9pchdir(FS *fs, const char *path)
53+{
54+ FS9p *aux = (void*)fs->aux;
55+
56+ aux->f = F9chdir;
57+
58+ return -1;
59+}
60+
61+static int
62+fs9popen(FS *fs, const char *name, FSmode mode)
63+{
64+ FS9p *aux = (void*)fs->aux;
65+
66+ aux->f = F9open;
67+
68+ return -1;
69+}
70+
71+static int
72+fs9pcreate(FS *fs, const char *path, int perm)
73+{
74+ FS9p *aux = (void*)fs->aux;
75+
76+ aux->f = F9create;
77+
78+ return -1;
79+}
80+
81+static int64_t
82+fs9pread(FS *fs, int fd, void *buf, uint64_t count)
83+{
84+ FS9p *aux = (void*)fs->aux;
85+
86+ aux->f = F9read;
87+
88+ return -1;
89+}
90+
91+static int64_t
92+fs9preaddir(FS *fs, int fd, FSstat *st, int nst)
93+{
94+ FS9p *aux = (void*)fs->aux;
95+
96+ aux->f = F9readdir;
97+
98+ return -1;
99+}
100+
101+static int64_t
102+fs9pwrite(FS *fs, int fd, const void *buf, uint64_t count)
103+{
104+ FS9p *aux = (void*)fs->aux;
105+
106+ aux->f = F9write;
107+
108+ return -1;
109+}
110+
111+static int64_t
112+fs9pseek(FS *fs, int fd, int64_t offset, int whence)
113+{
114+ FS9p *aux = (void*)fs->aux;
115+
116+ aux->f = F9seek;
117+
118+ return -1;
119+}
120+
121+static int
122+fs9pstat(FS *fs, const char *path, FSstat *st)
123+{
124+ FS9p *aux = (void*)fs->aux;
125+
126+ aux->f = F9stat;
127+
128+ return -1;
129+}
130+
131+static int
132+fs9pfstat(FS *fs, int fd, FSstat *st)
133+{
134+ FS9p *aux = (void*)fs->aux;
135+ C9tag tag;
136+ int e;
137+
138+ aux->f = F9fstat;
139+ aux->p = st;
140+ if((e = c9stat(aux->ctx, &tag, fd)) < 0)
141+ return e;
142+ while(aux->f != -F9fstat)
143+ c9proc(aux->ctx);
144+
145+ return 0;
146+}
147+
148+static int
149+fs9pclose(FS *fs, int fd)
150+{
151+ FS9p *aux = (void*)fs->aux;
152+
153+ aux->f = F9close;
154+
155+ return -1;
156+}
157+
158+static int
159+fs9premove(FS *fs, const char *name)
160+{
161+ FS9p *aux = (void*)fs->aux;
162+
163+ aux->f = F9remove;
164+
165+ return -1;
166+}
167+
168+static int
169+fs9prename(FS *fs, const char *oldpath, const char *newpath)
170+{
171+ FS9p *aux = (void*)fs->aux;
172+
173+ aux->f = F9rename;
174+
175+ return -1;
176+}
177+
178+static void
179+fs9pr(C9ctx *ctx, C9r *r)
180+{
181+ FSstat *st;
182+ C9tag tag;
183+ FS9p *aux;
184+ FS *fs;
185+
186+ fs = ctx->paux;
187+ aux = (void*)fs->aux;
188+
189+ switch(r->type){
190+ case Rversion:
191+ c9attach(ctx, &tag, FS9proot, C9nofid, "none", NULL); /* FIXME those need to be configurable */
192+ break;
193+
194+ case Rauth:
195+ break;
196+
197+ case Rattach:
198+ aux->flags |= Flinit;
199+ break;
200+
201+ case Rerror:
202+ fs->error(fs, "%s: %s", f2s[aux->f], r->error);
203+ aux->flags |= Flerror;
204+ break;
205+
206+ case Rflush:
207+ break;
208+
209+ case Rwalk:
210+ break;
211+
212+ case Ropen:
213+ break;
214+
215+ case Rcreate:
216+ break;
217+
218+ case Rread:
219+ break;
220+
221+ case Rwrite:
222+ break;
223+
224+ case Rclunk:
225+ break;
226+
227+ case Rremove:
228+ break;
229+
230+ case Rstat:
231+ if(aux->f == F9stat || aux->f == F9fstat){
232+ st = aux->p;
233+ st->size = r->stat.size;
234+ st->name = r->stat.name;
235+ st->uid = r->stat.uid;
236+ st->gid = r->stat.gid;
237+ st->mode = r->stat.mode;
238+ st->mtime = r->stat.mtime;
239+ aux->f = -aux->f;
240+ }
241+ break;
242+
243+ case Rwstat:
244+ break;
245+ }
246+}
247+
248+int
249+fs9pinit(FS *fs, uint32_t msize)
250+{
251+ FS9p *aux = (void*)fs->aux;
252+ C9error err;
253+ C9tag tag;
254+ int i;
255+
256+ if(fs->error == NULL)
257+ return -1;
258+ if(aux == NULL || aux->ctx == NULL || aux->fds == NULL || aux->numfds < 1){
259+ fs->error(fs, "fs9pinit: invalid aux");
260+ return -1;
261+ }
262+ if(aux->ctx == NULL){
263+ fs->error(fs, "fs9pinit: invalid ctx");
264+ return -1;
265+ }
266+
267+ fs->chdir = fs9pchdir;
268+ fs->open = fs9popen;
269+ fs->create = fs9pcreate;
270+ fs->read = fs9pread;
271+ fs->readdir = fs9preaddir;
272+ fs->write = fs9pwrite;
273+ fs->seek = fs9pseek;
274+ fs->stat = fs9pstat;
275+ fs->fstat = fs9pfstat;
276+ fs->close = fs9pclose;
277+ fs->remove = fs9premove;
278+ fs->rename = fs9prename;
279+
280+ aux->root.offset = 0;
281+ for(i = 0; i < aux->numfds; i++)
282+ aux->fds[i] = freefd;
283+
284+ aux->ctx->r = fs9pr;
285+ aux->ctx->paux = fs;
286+ aux->f = F9init;
287+ aux->flags = 0;
288+
289+ if((err = c9version(aux->ctx, &tag, msize)) != 0)
290+ return err;
291+ for(;;){
292+ if((err = c9proc(aux->ctx)) != 0)
293+ return err;
294+ if(aux->flags & Flerror)
295+ return -1;
296+ if(aux->flags & Flinit)
297+ break;
298+ }
299+
300+ return 0;
301+}
include/c9/fs.h+48−0
@@ -0,0 +1,48 @@
1+typedef struct FS FS;
2+typedef struct FSstat FSstat;
3+
4+typedef enum
5+{
6+ FS_OREAD,
7+ FS_OWRITE,
8+ FS_ORDWR,
9+ FS_OEXEC,
10+ FS_OTRUNC = 0x10,
11+ FS_ORCLOSE = 0x40,
12+ FS_OEXCL = 0x1000,
13+ FS_DIR = 0x80000000U, /* open/create: it's supposed to be a directory. */
14+}FSmode;
15+
16+struct FSstat
17+{
18+ uint64_t size; /* Size of the file (in bytes). */
19+ char *name; /* Name of the file. */
20+ char *uid; /* Owner of the file. */
21+ char *gid; /* Group of the file. */
22+ uint32_t mode; /* Permissions. See C9st* and C9perm. */
23+ uint64_t mtime; /* Last modification time. Nanoseconds since epoch. */
24+};
25+
26+struct FSaux;
27+
28+struct FS
29+{
30+ /* Callback for error messages. */
31+ void (*error)(FS *fs, const char *fmt, ...) __attribute__((nonnull(1), format(printf, 2, 3)));
32+
33+ /* Do not set these. */
34+ int (*chdir)(FS *fs, const char *path) __attribute__((nonnull(1, 2)));
35+ int (*open)(FS *fs, const char *name, FSmode mode) __attribute__((nonnull(1, 2)));
36+ int (*create)(FS *fs, const char *path, int perm) __attribute__((nonnull(1, 2)));
37+ int64_t (*read)(FS *fs, int fd, void *buf, uint64_t count) __attribute__((nonnull(1, 3)));
38+ int64_t (*readdir)(FS *fs, int fd, FSstat *st, int nst);
39+ int64_t (*write)(FS *fs, int fd, const void *buf, uint64_t count) __attribute__((nonnull(1, 3)));
40+ int64_t (*seek)(FS *fs, int fd, int64_t offset, int whence) __attribute__((nonnull(1)));
41+ int (*stat)(FS *fs, const char *path, FSstat *st) __attribute__((nonnull(1, 2, 3)));
42+ int (*fstat)(FS *fs, int fd, FSstat *st) __attribute__((nonnull(1, 3)));
43+ int (*close)(FS *fs, int fd) __attribute__((nonnull(1)));
44+ int (*remove)(FS *fs, const char *name) __attribute__((nonnull(1, 2)));
45+ int (*rename)(FS *fs, const char *oldpath, const char *newpath) __attribute__((nonnull(1, 2, 3)));
46+
47+ struct FSaux *aux;
48+};
include/c9/fs9p.h+31−0
@@ -0,0 +1,31 @@
1+enum
2+{
3+ FS9proot = 3, /* '/' file descriptor. */
4+};
5+
6+typedef struct FS9p FS9p;
7+typedef struct FS9pfd FS9pfd;
8+
9+struct FS9pfd
10+{
11+ uint64_t offset;
12+};
13+
14+struct FS9p
15+{
16+ /* The following three fields need to be set before calling fs9pinit. */
17+
18+ C9ctx *ctx; /* Set to a full set up context, except "r" and "t" fields. */
19+ FS9pfd *fds; /* Point at the allocated fds array. */
20+ int numfds; /* Set to the number of entries available in fds array. */
21+ void *aux; /* Optional, user-supplied aux value. */
22+
23+ /* Private, do not touch. */
24+ FS9pfd root;
25+ FS9pfd cwd;
26+ int f;
27+ void *p;
28+ int flags;
29+};
30+
31+extern int fs9pinit(FS *fs, uint32_t msize) __attribute__((nonnull(1)));
include/c9/proto.hrenamed from c9.h+6−10
@@ -1,12 +1,3 @@
1−#ifdef __plan9__
2−typedef u64int uint64_t;
3−typedef u32int uint32_t;
4−typedef u16int uint16_t;
5−typedef u8int uint8_t;
6−#define __attribute__(...)
7−#define NULL nil
8−#endif
9−
101 struct C9aux;
112
123 typedef struct C9r C9r;
@@ -295,12 +286,13 @@ struct C9ctx · 282 unmodified lines
295286 void (*t)(C9ctx *ctx, C9t *t) __attribute__((nonnull(1, 2)));
296287
297288 /* Callback for error messages. */
298− void (*error)(const char *fmt, ...) __attribute__((nonnull(1), format(printf, 1, 2)));
289+ void (*error)(C9ctx *ctx, const char *fmt, ...) __attribute__((nonnull(1), format(printf, 2, 3)));
299290
300291 /* Auxiliary data, can be used by any of above callbacks. */
301292 struct C9aux *aux;
302293
303294 /* private stuff */
295+ void *paux;
304296 uint32_t msize;
305297 #ifndef C9_NO_CLIENT
306298 uint32_t flush[C9maxflush];
@@ -308,8 +300,12 @@ struct C9ctx · 1 unmodified line
308300 #endif
309301 union
310302 {
303+#ifndef C9_NO_CLIENT
311304 C9tag lowfreetag;
305+#endif
306+#ifndef C9_NO_SERVER
312307 uint16_t svflags;
308+#endif
313309 };
314310 };
315311
proto.crenamed from c9.c+40−52
@@ -1,18 +1,6 @@
1−/*
2− * This is 9p client and server implementation which aims to be
3− * correct, small and secure. It's the lowest level implementation.
4− * It doesn't have much comments, mostly because it doesn't make
5− * any sense to copy-paste protocol documentation, which
6− * you can read at http://man.cat-v.org/plan_9/5/, see 'intro'.
7− */
8−#ifdef __plan9__
9−#include <u.h>
10−#include <libc.h>
11−#else
121 #include <stdint.h>
132 #include <string.h>
14−#endif
15−#include "c9.h"
3+#include "c9/proto.h"
164
175 enum
186 {
@@ -138,7 +126,7 @@ newtag(C9ctx *c, C9ttype type, C9tag *tag) · 119 unmodified lines
138126 }
139127 }
140128
141− c->error("newtag: no free tags");
129+ c->error(c, "newtag: no free tags");
142130 return C9Etag;
143131 }
144132
@@ -148,11 +136,11 @@ freetag(C9ctx *c, C9tag tag) · 3 unmodified lines
148136 if(tag != 0xffff){
149137 uint32_t d = tag / C9tagsbits, m = tag % C9tagsbits;
150138 if(tag >= C9maxtags){
151− c->error("freetag: invalid tag %ud", (uint32_t)tag);
139+ c->error(c, "freetag: invalid tag %ud", (uint32_t)tag);
152140 return -1;
153141 }
154142 if((c->tags[d] & 1<<m) != 0){
155− c->error("freetag: double free for tag %ud", (uint32_t)tag);
143+ c->error(c, "freetag: double free for tag %ud", (uint32_t)tag);
156144 return -1;
157145 }
158146 if(c->lowfreetag > tag)
@@ -168,12 +156,12 @@ T(C9ctx *c, uint32_t size, C9ttype type, C9tag *tag, C9error *err) · 9 unmodified lines
168156 uint8_t *p = NULL;
169157
170158 if(size > c->msize-4-1-2){
171− c->error("T: invalid size %ud", size);
159+ c->error(c, "T: invalid size %ud", size);
172160 *err = C9Esize;
173161 }else if((*err = newtag(c, type, tag)) == 0){
174162 size += 4+1+2;
175163 if((p = c->begin(c, size)) == NULL){
176− c->error("T: no buffer for %ud bytes", size);
164+ c->error(c, "T: no buffer for %ud bytes", size);
177165 freetag(c, *tag);
178166 *err = C9Ebuf;
179167 }else{
@@ -193,7 +181,7 @@ c9version(C9ctx *c, C9tag *tag, uint32_t msize) · 13 unmodified lines
193181 C9error err;
194182
195183 if(msize < C9minmsize){
196− c->error("c9version: msize too small: %ud", msize);
184+ c->error(c, "c9version: msize too small: %ud", msize);
197185 return C9Einit;
198186 }
199187 memset(c->tags, 0xff, sizeof(c->tags));
@@ -217,7 +205,7 @@ c9auth(C9ctx *c, C9tag *tag, C9fid afid, const char *uname, const char *aname) · 17 unmodified lines
217205 C9error err;
218206
219207 if(ulen > C9maxstr || alen > C9maxstr){
220− c->error("c9auth: string too long: %ud chars", ulen > alen ? ulen : alen);
208+ c->error(c, "c9auth: string too long: %ud chars", ulen > alen ? ulen : alen);
221209 return C9Estr;
222210 }
223211 if((b = T(c, 4+2+ulen+2+alen, Tauth, tag, &err)) != NULL){
@@ -238,7 +226,7 @@ c9flush(C9ctx *c, C9tag *tag, C9tag oldtag) · 14 unmodified lines
238226
239227 for(i = 0; i < C9maxflush && c->flush[i] != (uint32_t)~0; i++);
240228 if(i == C9maxflush){
241− c->error("c9flush: no free flush slots");
229+ c->error(c, "c9flush: no free flush slots");
242230 return C9Eflush;
243231 }
244232 if((b = T(c, 2, Tflush, tag, &err)) != NULL){
@@ -258,7 +246,7 @@ c9attach(C9ctx *c, C9tag *tag, C9fid fid, C9fid afid, const char *uname, const c · 13 unmodified lines
258246 C9error err;
259247
260248 if(ulen > C9maxstr || alen > C9maxstr){
261− c->error("c9attach: string too long: %ud chars", ulen > alen ? ulen : alen);
249+ c->error(c, "c9attach: string too long: %ud chars", ulen > alen ? ulen : alen);
262250 return C9Estr;
263251 }
264252 if((b = T(c, 4+4+2+ulen+2+alen, Tattach, tag, &err)) != NULL){
@@ -282,13 +270,13 @@ c9walk(C9ctx *c, C9tag *tag, C9fid fid, C9fid newfid, const char *path[]) · 17 unmodified lines
282270 for(sz = i = 0; i < (int)sizeof(len)/sizeof(len[0]) && path[i] != NULL; i++){
283271 len[i] = safestrlen(path[i]);
284272 if(len[i] == 0 || len[i] > C9maxstr){
285− c->error("c9walk: invalid path element: %ud chars", len[i]);
273+ c->error(c, "c9walk: invalid path element: %ud chars", len[i]);
286274 return C9Epath;
287275 }
288276 sz += 2 + len[i];
289277 }
290278 if(path[i] != NULL){
291− c->error("c9walk: invalid elements !(0 <= %ud <= %ud)", i, C9maxpathel);
279+ c->error(c, "c9walk: invalid elements !(0 <= %ud <= %ud)", i, C9maxpathel);
292280 return C9Epath;
293281 }
294282
@@ -325,7 +313,7 @@ c9create(C9ctx *c, C9tag *tag, C9fid fid, const char *name, uint32_t perm, C9mod · 30 unmodified lines
325313 C9error err;
326314
327315 if(nlen == 0 || nlen > C9maxstr){
328− c->error("c9create: invalid name: %ud chars", nlen);
316+ c->error(c, "c9create: invalid name: %ud chars", nlen);
329317 return C9Epath;
330318 }
331319 if((b = T(c, 4+2+nlen+4+1, Tcreate, tag, &err)) != NULL){
@@ -423,11 +411,11 @@ c9wstat(C9ctx *c, C9tag *tag, C9fid fid, const C9stat *s) · 91 unmodified lines
423411 C9error err;
424412
425413 if(nlen == 0 || nlen > C9maxstr){
426− c->error("c9wstat: invalid name: %ud chars", nlen);
414+ c->error(c, "c9wstat: invalid name: %ud chars", nlen);
427415 return C9Epath;
428416 }
429417 if(ulen > C9maxstr || glen > C9maxstr){
430− c->error("c9wstat: string too long: %ud chars", ulen > glen ? ulen : glen);
418+ c->error(c, "c9wstat: string too long: %ud chars", ulen > glen ? ulen : glen);
431419 return C9Estr;
432420 }
433421 if((b = T(c, 4+2+2+statsz, Twstat, tag, &err)) != NULL){
@@ -460,20 +448,20 @@ c9proc(C9ctx *c) · 26 unmodified lines
460448 err = -1;
461449 if((b = c->read(c, 4, &err)) == NULL){
462450 if(err != 0)
463− c->error("c9proc: short read");
451+ c->error(c, "c9proc: short read");
464452 return err == 0 ? 0 : C9Epkt;
465453 }
466454
467455 sz = r32(&b);
468456 if(sz < 7 || sz > c->msize){
469− c->error("c9proc: invalid packet size !(7 <= %ud <= %ud)", sz, c->msize);
457+ c->error(c, "c9proc: invalid packet size !(7 <= %ud <= %ud)", sz, c->msize);
470458 return C9Epkt;
471459 }
472460 sz -= 4;
473461 err = -1;
474462 if((b = c->read(c, sz, &err)) == NULL){
475463 if(err != 0)
476− c->error("c9proc: short read");
464+ c->error(c, "c9proc: short read");
477465 return err == 0 ? 0 : C9Epkt;
478466 }
479467
@@ -481,7 +469,7 @@ c9proc(C9ctx *c) · 1 unmodified line
481469 r.tag = r16(&b);
482470 if(r.type != Rversion){
483471 if(r.tag >= C9maxtags){
484− c->error("c9proc: invalid tag %ud", (uint32_t)r.tag);
472+ c->error(c, "c9proc: invalid tag %ud", (uint32_t)r.tag);
485473 return C9Epkt;
486474 }
487475 if(freetag(c, r.tag) != 0)
@@ -510,7 +498,7 @@ c9proc(C9ctx *c) · 22 unmodified lines
510498 if(sz < 2 || (cnt = r16(&b))*13 > sz-2)
511499 goto error;
512500 if(cnt > C9maxpathel){
513− c->error("c9proc: Rwalk !(%ud <= %ud)", cnt, C9maxpathel);
501+ c->error(c, "c9proc: Rwalk !(%ud <= %ud)", cnt, C9maxpathel);
514502 return C9Epath;
515503 }
516504 for(i = 0; i < cnt; i++){
@@ -580,7 +568,7 @@ c9proc(C9ctx *c) · 63 unmodified lines
580568 if(sz < 4+2 || (msize = r32(&b)) < C9minmsize || (cnt = r16(&b)) > sz-4-2)
581569 goto error;
582570 if(cnt < 6 || memcmp(b, "9P2000", 6) != 0){
583− c->error("invalid version");
571+ c->error(c, "invalid version");
584572 return C9Ever;
585573 }
586574 if(msize < c->msize)
@@ -593,7 +581,7 @@ c9proc(C9ctx *c) · 6 unmodified lines
593581 }
594582 return 0;
595583 error:
596− c->error("c9proc: invalid packet type %ud", r.type);
584+ c->error(c, "c9proc: invalid packet type %ud", r.type);
597585 return C9Epkt;
598586 }
599587
@@ -633,7 +621,7 @@ c9parsedir(C9ctx *c, C9stat *stat, uint8_t **t, uint32_t *size) · 33 unmodified lines
633621 *t += sz;
634622 return 0;
635623 error:
636− c->error("c9parsedir: invalid size: size=%ud sz=%ud", *size, sz);
624+ c->error(c, "c9parsedir: invalid size: size=%ud sz=%ud", *size, sz);
637625 return C9Epkt;
638626 }
639627
@@ -645,12 +633,12 @@ R(C9ctx *c, uint32_t size, C9rtype type, C9tag tag, C9error *err) · 5 unmodified lines
645633 uint8_t *p = NULL;
646634
647635 if(size > c->msize-4-1-2){
648− c->error("R: invalid size %ud", size);
636+ c->error(c, "R: invalid size %ud", size);
649637 *err = C9Esize;
650638 }else{
651639 size += 4+1+2;
652640 if((p = c->begin(c, size)) == NULL){
653− c->error("R: no buffer for %ud bytes", size);
641+ c->error(c, "R: no buffer for %ud bytes", size);
654642 *err = C9Ebuf;
655643 }else{
656644 *err = 0;
@@ -699,7 +687,7 @@ s9error(C9ctx *c, C9tag tag, const char *ename) · 42 unmodified lines
699687 C9error err;
700688
701689 if(len > C9maxstr){
702− c->error("s9error: invalid ename: %ud chars", len);
690+ c->error(c, "s9error: invalid ename: %ud chars", len);
703691 return C9Estr;
704692 }
705693 if((b = R(c, 2+len, Rerror, tag, &err)) != NULL){
@@ -743,7 +731,7 @@ s9walk(C9ctx *c, C9tag tag, C9qid *qids[]) · 37 unmodified lines
743731
744732 for(n = 0; n < C9maxpathel && qids[n] != NULL; n++);
745733 if(n > C9maxpathel){
746− c->error("s9walk: invalid elements !(0 <= %ud <= %ud)", n, C9maxpathel);
734+ c->error(c, "s9walk: invalid elements !(0 <= %ud <= %ud)", n, C9maxpathel);
747735 return C9Epath;
748736 }
749737
@@ -839,13 +827,13 @@ s9readdir(C9ctx *c, C9tag tag, C9stat *st[], int *num, uint64_t *offset, uint32_ · 89 unmodified lines
839827 mulen = safestrlen(s->muid);
840828
841829 if(nlen == 0 || nlen > C9maxstr){
842− c->error("s9readdir: invalid name: %ud chars", nlen);
830+ c->error(c, "s9readdir: invalid name: %ud chars", nlen);
843831 return C9Epath;
844832 }
845833 if(ulen > C9maxstr || glen > C9maxstr || mulen > C9maxstr){
846834 ulen = ulen > glen ? ulen : glen;
847835 ulen = ulen > mulen ? ulen : mulen;
848− c->error("s9readdir: string too long: %ud chars", ulen);
836+ c->error(c, "s9readdir: string too long: %ud chars", ulen);
849837 return C9Estr;
850838 }
851839
@@ -916,13 +904,13 @@ s9stat(C9ctx *c, C9tag tag, const C9stat *s) · 64 unmodified lines
916904 C9error err;
917905
918906 if(nlen == 0 || nlen > C9maxstr){
919− c->error("s9stat: invalid name: %ud chars", nlen);
907+ c->error(c, "s9stat: invalid name: %ud chars", nlen);
920908 return C9Epath;
921909 }
922910 if(ulen > C9maxstr || glen > C9maxstr || mulen > C9maxstr){
923911 ulen = ulen > glen ? ulen : glen;
924912 ulen = ulen > mulen ? ulen : mulen;
925− c->error("s9stat: string too long: %ud chars", ulen);
913+ c->error(c, "s9stat: string too long: %ud chars", ulen);
926914 return C9Estr;
927915 }
928916
@@ -969,20 +957,20 @@ s9proc(C9ctx *c) · 40 unmodified lines
969957 readerr = -1;
970958 if((b = c->read(c, 4, &readerr)) == NULL){
971959 if(readerr != 0)
972− c->error("s9proc: short read");
960+ c->error(c, "s9proc: short read");
973961 return readerr == 0 ? 0 : C9Epkt;
974962 }
975963
976964 sz = r32(&b);
977965 if(sz < 7 || sz > c->msize){
978− c->error("s9proc: invalid packet size !(7 <= %ud <= %ud)", sz, c->msize);
966+ c->error(c, "s9proc: invalid packet size !(7 <= %ud <= %ud)", sz, c->msize);
979967 return C9Epkt;
980968 }
981969 sz -= 4;
982970 readerr = -1;
983971 if((b = c->read(c, sz, &readerr)) == NULL){
984972 if(readerr != 0)
985− c->error("s9proc: short read");
973+ c->error(c, "s9proc: short read");
986974 return readerr == 0 ? 0 : C9Epkt;
987975 }
988976
@@ -991,7 +979,7 @@ s9proc(C9ctx *c) · 2 unmodified lines
991979 sz -= 3;
992980
993981 if((c->svflags & Svver) == 0 && t.type != Tversion){
994− c->error("s9proc: expected Tversion, got %ud", t.type);
982+ c->error(c, "s9proc: expected Tversion, got %ud", t.type);
995983 return C9Epkt;
996984 }
997985
@@ -1035,7 +1023,7 @@ s9proc(C9ctx *c) · 37 unmodified lines
10351023 t.fid = r32(&b);
10361024 t.walk.newfid = r32(&b);
10371025 if((n = r16(&b)) > 16){
1038− c->error("s9proc: Twalk !(%ud <= 16)", n);
1026+ c->error(c, "s9proc: Twalk !(%ud <= 16)", n);
10391027 return C9Epath;
10401028 }
10411029 sz -= 4+4+2;
@@ -1044,7 +1032,7 @@ s9proc(C9ctx *c) · 2 unmodified lines
10441032 if(sz < 2 || (cnt = r16(&b)) > sz-2)
10451033 goto error;
10461034 if(cnt < 1){
1047− c->error("s9proc: Twalk invalid element [%ud]", i);
1035+ c->error(c, "s9proc: Twalk invalid element [%ud]", i);
10481036 return C9Epath;
10491037 }
10501038 b[-2] = 0;
@@ -1076,7 +1064,7 @@ s9proc(C9ctx *c) · 25 unmodified lines
10761064 if((cnt = r16(&b)) > sz-4)
10771065 goto error;
10781066 if((err = c9parsedir(c, &t.wstat, &b, &cnt)) != 0){
1079− c->error("s9proc");
1067+ c->error(c, "s9proc");
10801068 return err;
10811069 }
10821070 c->t(c, &t);
@@ -1111,7 +1099,7 @@ s9proc(C9ctx *c) · 28 unmodified lines
11111099 w32(&b, 0);
11121100 wcs(&b, "unknown", 7);
11131101 err = c->end(c);
1114− c->error("s9proc: invalid version");
1102+ c->error(c, "s9proc: invalid version");
11151103 }
11161104 return C9Ever;
11171105 }
@@ -1169,7 +1157,7 @@ s9proc(C9ctx *c) · 51 unmodified lines
11691157 }
11701158 return 0;
11711159 error:
1172− c->error("s9proc: invalid packet (type=%ud)", t.type);
1160+ c->error(c, "s9proc: invalid packet (type=%ud)", t.type);
11731161 return C9Epkt;
11741162 }
11751163

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t