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 @@
1# c91# c9
2 2
3Low level 9p client and server.3NOTE (2022-06-27): the library's (yep, it's going to be a library)
4API is getting completely revamped, and examples are being added.
5Use either an older version, or expect API breakage.
4 6
5## Examples7A lightweight library for implmeneting 9p clients and servers in C.
6 8
7Until I have time to write a minimal example you could take a look at 9This is 9p client and server implementation which aims to be correct,
8https://git.sr.ht/~ft/9pro/blob/master/9pex.c10small 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
18context created with `proto.[ch]` one can use POSIX-like file API to
19work with a remote filesystem.
20
21Goals:
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
8int
9dial(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
8int dial(const char *s);
9C9ctx *init9p(int f);
10
11static FS9pfd fds[8];
12
13static void
14fserror(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
25int
26main(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
9enum {
10 Msize = 8192,
11
12 Disconnected = 1<<0,
13};
14
15typedef struct C9aux C9aux;
16
17struct 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
26static uint8_t *
27ctxread(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
48static int
49wrsend(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
68static uint8_t *
69ctxbegin(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
85static int
86ctxend(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
98static void
99ctxerror(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
110C9aux *
111init9p(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
7enum
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
27static const FS9pfd freefd =
28{
29 .offset = ~0ULL,
30};
31
32#define isfree(fd) ((fd).offset == ~0ULL)
33
34static 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
51static int
52fs9pchdir(FS *fs, const char *path)
53{
54 FS9p *aux = (void*)fs->aux;
55
56 aux->f = F9chdir;
57
58 return -1;
59}
60
61static int
62fs9popen(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
71static int
72fs9pcreate(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
81static int64_t
82fs9pread(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
91static int64_t
92fs9preaddir(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
101static int64_t
102fs9pwrite(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
111static int64_t
112fs9pseek(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
121static int
122fs9pstat(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
131static int
132fs9pfstat(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
148static int
149fs9pclose(FS *fs, int fd)
150{
151 FS9p *aux = (void*)fs->aux;
152
153 aux->f = F9close;
154
155 return -1;
156}
157
158static int
159fs9premove(FS *fs, const char *name)
160{
161 FS9p *aux = (void*)fs->aux;
162
163 aux->f = F9remove;
164
165 return -1;
166}
167
168static int
169fs9prename(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
178static void
179fs9pr(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
248int
249fs9pinit(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 @@
1typedef struct FS FS;
2typedef struct FSstat FSstat;
3
4typedef 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
16struct 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
26struct FSaux;
27
28struct 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 @@
1enum
2{
3 FS9proot = 3, /* '/' file descriptor. */
4};
5
6typedef struct FS9p FS9p;
7typedef struct FS9pfd FS9pfd;
8
9struct FS9pfd
10{
11 uint64_t offset;
12};
13
14struct 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
31extern 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__
2typedef u64int uint64_t;
3typedef u32int uint32_t;
4typedef u16int uint16_t;
5typedef u8int uint8_t;
6#define __attribute__(...)
7#define NULL nil
8#endif
9
10struct C9aux;1struct C9aux;
11 2
12typedef struct C9r C9r;3typedef struct C9r C9r;
@@ -295,12 +286,13 @@ struct C9ctx · 282 unmodified lines
295 void (*t)(C9ctx *ctx, C9t *t) __attribute__((nonnull(1, 2)));286 void (*t)(C9ctx *ctx, C9t *t) __attribute__((nonnull(1, 2)));
296 287
297 /* Callback for error messages. */288 /* 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)));
299 290
300 /* Auxiliary data, can be used by any of above callbacks. */291 /* Auxiliary data, can be used by any of above callbacks. */
301 struct C9aux *aux;292 struct C9aux *aux;
302 293
303 /* private stuff */294 /* private stuff */
295 void *paux;
304 uint32_t msize;296 uint32_t msize;
305#ifndef C9_NO_CLIENT297#ifndef C9_NO_CLIENT
306 uint32_t flush[C9maxflush];298 uint32_t flush[C9maxflush];
@@ -308,8 +300,12 @@ struct C9ctx · 1 unmodified line
308#endif300#endif
309 union301 union
310 {302 {
303#ifndef C9_NO_CLIENT
311 C9tag lowfreetag;304 C9tag lowfreetag;
305#endif
306#ifndef C9_NO_SERVER
312 uint16_t svflags;307 uint16_t svflags;
308#endif
313 };309 };
314};310};
315 311
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
12#include <stdint.h>1#include <stdint.h>
13#include <string.h>2#include <string.h>
14#endif3#include "c9/proto.h"
15#include "c9.h"
16 4
17enum5enum
18{6{
@@ -138,7 +126,7 @@ newtag(C9ctx *c, C9ttype type, C9tag *tag) · 119 unmodified lines
138 }126 }
139 }127 }
140 128
141 c->error("newtag: no free tags");129 c->error(c, "newtag: no free tags");
142 return C9Etag;130 return C9Etag;
143}131}
144 132
@@ -148,11 +136,11 @@ freetag(C9ctx *c, C9tag tag) · 3 unmodified lines
148 if(tag != 0xffff){136 if(tag != 0xffff){
149 uint32_t d = tag / C9tagsbits, m = tag % C9tagsbits;137 uint32_t d = tag / C9tagsbits, m = tag % C9tagsbits;
150 if(tag >= C9maxtags){138 if(tag >= C9maxtags){
151 c->error("freetag: invalid tag %ud", (uint32_t)tag);139 c->error(c, "freetag: invalid tag %ud", (uint32_t)tag);
152 return -1;140 return -1;
153 }141 }
154 if((c->tags[d] & 1<<m) != 0){142 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);
156 return -1;144 return -1;
157 }145 }
158 if(c->lowfreetag > tag)146 if(c->lowfreetag > tag)
@@ -168,12 +156,12 @@ T(C9ctx *c, uint32_t size, C9ttype type, C9tag *tag, C9error *err) · 9 unmodified lines
168 uint8_t *p = NULL;156 uint8_t *p = NULL;
169 157
170 if(size > c->msize-4-1-2){158 if(size > c->msize-4-1-2){
171 c->error("T: invalid size %ud", size);159 c->error(c, "T: invalid size %ud", size);
172 *err = C9Esize;160 *err = C9Esize;
173 }else if((*err = newtag(c, type, tag)) == 0){161 }else if((*err = newtag(c, type, tag)) == 0){
174 size += 4+1+2;162 size += 4+1+2;
175 if((p = c->begin(c, size)) == NULL){163 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);
177 freetag(c, *tag);165 freetag(c, *tag);
178 *err = C9Ebuf;166 *err = C9Ebuf;
179 }else{167 }else{
@@ -193,7 +181,7 @@ c9version(C9ctx *c, C9tag *tag, uint32_t msize) · 13 unmodified lines
193 C9error err;181 C9error err;
194 182
195 if(msize < C9minmsize){183 if(msize < C9minmsize){
196 c->error("c9version: msize too small: %ud", msize);184 c->error(c, "c9version: msize too small: %ud", msize);
197 return C9Einit;185 return C9Einit;
198 }186 }
199 memset(c->tags, 0xff, sizeof(c->tags));187 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
217 C9error err;205 C9error err;
218 206
219 if(ulen > C9maxstr || alen > C9maxstr){207 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);
221 return C9Estr;209 return C9Estr;
222 }210 }
223 if((b = T(c, 4+2+ulen+2+alen, Tauth, tag, &err)) != NULL){211 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
238 226
239 for(i = 0; i < C9maxflush && c->flush[i] != (uint32_t)~0; i++);227 for(i = 0; i < C9maxflush && c->flush[i] != (uint32_t)~0; i++);
240 if(i == C9maxflush){228 if(i == C9maxflush){
241 c->error("c9flush: no free flush slots");229 c->error(c, "c9flush: no free flush slots");
242 return C9Eflush;230 return C9Eflush;
243 }231 }
244 if((b = T(c, 2, Tflush, tag, &err)) != NULL){232 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
258 C9error err;246 C9error err;
259 247
260 if(ulen > C9maxstr || alen > C9maxstr){248 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);
262 return C9Estr;250 return C9Estr;
263 }251 }
264 if((b = T(c, 4+4+2+ulen+2+alen, Tattach, tag, &err)) != NULL){252 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
282 for(sz = i = 0; i < (int)sizeof(len)/sizeof(len[0]) && path[i] != NULL; i++){270 for(sz = i = 0; i < (int)sizeof(len)/sizeof(len[0]) && path[i] != NULL; i++){
283 len[i] = safestrlen(path[i]);271 len[i] = safestrlen(path[i]);
284 if(len[i] == 0 || len[i] > C9maxstr){272 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]);
286 return C9Epath;274 return C9Epath;
287 }275 }
288 sz += 2 + len[i];276 sz += 2 + len[i];
289 }277 }
290 if(path[i] != NULL){278 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);
292 return C9Epath;280 return C9Epath;
293 }281 }
294 282
@@ -325,7 +313,7 @@ c9create(C9ctx *c, C9tag *tag, C9fid fid, const char *name, uint32_t perm, C9mod · 30 unmodified lines
325 C9error err;313 C9error err;
326 314
327 if(nlen == 0 || nlen > C9maxstr){315 if(nlen == 0 || nlen > C9maxstr){
328 c->error("c9create: invalid name: %ud chars", nlen);316 c->error(c, "c9create: invalid name: %ud chars", nlen);
329 return C9Epath;317 return C9Epath;
330 }318 }
331 if((b = T(c, 4+2+nlen+4+1, Tcreate, tag, &err)) != NULL){319 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
423 C9error err;411 C9error err;
424 412
425 if(nlen == 0 || nlen > C9maxstr){413 if(nlen == 0 || nlen > C9maxstr){
426 c->error("c9wstat: invalid name: %ud chars", nlen);414 c->error(c, "c9wstat: invalid name: %ud chars", nlen);
427 return C9Epath;415 return C9Epath;
428 }416 }
429 if(ulen > C9maxstr || glen > C9maxstr){417 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);
431 return C9Estr;419 return C9Estr;
432 }420 }
433 if((b = T(c, 4+2+2+statsz, Twstat, tag, &err)) != NULL){421 if((b = T(c, 4+2+2+statsz, Twstat, tag, &err)) != NULL){
@@ -460,20 +448,20 @@ c9proc(C9ctx *c) · 26 unmodified lines
460 err = -1;448 err = -1;
461 if((b = c->read(c, 4, &err)) == NULL){449 if((b = c->read(c, 4, &err)) == NULL){
462 if(err != 0)450 if(err != 0)
463 c->error("c9proc: short read");451 c->error(c, "c9proc: short read");
464 return err == 0 ? 0 : C9Epkt;452 return err == 0 ? 0 : C9Epkt;
465 }453 }
466 454
467 sz = r32(&b);455 sz = r32(&b);
468 if(sz < 7 || sz > c->msize){456 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);
470 return C9Epkt;458 return C9Epkt;
471 }459 }
472 sz -= 4;460 sz -= 4;
473 err = -1;461 err = -1;
474 if((b = c->read(c, sz, &err)) == NULL){462 if((b = c->read(c, sz, &err)) == NULL){
475 if(err != 0)463 if(err != 0)
476 c->error("c9proc: short read");464 c->error(c, "c9proc: short read");
477 return err == 0 ? 0 : C9Epkt;465 return err == 0 ? 0 : C9Epkt;
478 }466 }
479 467
@@ -481,7 +469,7 @@ c9proc(C9ctx *c) · 1 unmodified line
481 r.tag = r16(&b);469 r.tag = r16(&b);
482 if(r.type != Rversion){470 if(r.type != Rversion){
483 if(r.tag >= C9maxtags){471 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);
485 return C9Epkt;473 return C9Epkt;
486 }474 }
487 if(freetag(c, r.tag) != 0)475 if(freetag(c, r.tag) != 0)
@@ -510,7 +498,7 @@ c9proc(C9ctx *c) · 22 unmodified lines
510 if(sz < 2 || (cnt = r16(&b))*13 > sz-2)498 if(sz < 2 || (cnt = r16(&b))*13 > sz-2)
511 goto error;499 goto error;
512 if(cnt > C9maxpathel){500 if(cnt > C9maxpathel){
513 c->error("c9proc: Rwalk !(%ud <= %ud)", cnt, C9maxpathel);501 c->error(c, "c9proc: Rwalk !(%ud <= %ud)", cnt, C9maxpathel);
514 return C9Epath;502 return C9Epath;
515 }503 }
516 for(i = 0; i < cnt; i++){504 for(i = 0; i < cnt; i++){
@@ -580,7 +568,7 @@ c9proc(C9ctx *c) · 63 unmodified lines
580 if(sz < 4+2 || (msize = r32(&b)) < C9minmsize || (cnt = r16(&b)) > sz-4-2)568 if(sz < 4+2 || (msize = r32(&b)) < C9minmsize || (cnt = r16(&b)) > sz-4-2)
581 goto error;569 goto error;
582 if(cnt < 6 || memcmp(b, "9P2000", 6) != 0){570 if(cnt < 6 || memcmp(b, "9P2000", 6) != 0){
583 c->error("invalid version");571 c->error(c, "invalid version");
584 return C9Ever;572 return C9Ever;
585 }573 }
586 if(msize < c->msize)574 if(msize < c->msize)
@@ -593,7 +581,7 @@ c9proc(C9ctx *c) · 6 unmodified lines
593 }581 }
594 return 0;582 return 0;
595error:583error:
596 c->error("c9proc: invalid packet type %ud", r.type);584 c->error(c, "c9proc: invalid packet type %ud", r.type);
597 return C9Epkt;585 return C9Epkt;
598}586}
599 587
@@ -633,7 +621,7 @@ c9parsedir(C9ctx *c, C9stat *stat, uint8_t **t, uint32_t *size) · 33 unmodified lines
633 *t += sz;621 *t += sz;
634 return 0;622 return 0;
635error:623error:
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);
637 return C9Epkt;625 return C9Epkt;
638}626}
639 627
@@ -645,12 +633,12 @@ R(C9ctx *c, uint32_t size, C9rtype type, C9tag tag, C9error *err) · 5 unmodified lines
645 uint8_t *p = NULL;633 uint8_t *p = NULL;
646 634
647 if(size > c->msize-4-1-2){635 if(size > c->msize-4-1-2){
648 c->error("R: invalid size %ud", size);636 c->error(c, "R: invalid size %ud", size);
649 *err = C9Esize;637 *err = C9Esize;
650 }else{638 }else{
651 size += 4+1+2;639 size += 4+1+2;
652 if((p = c->begin(c, size)) == NULL){640 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);
654 *err = C9Ebuf;642 *err = C9Ebuf;
655 }else{643 }else{
656 *err = 0;644 *err = 0;
@@ -699,7 +687,7 @@ s9error(C9ctx *c, C9tag tag, const char *ename) · 42 unmodified lines
699 C9error err;687 C9error err;
700 688
701 if(len > C9maxstr){689 if(len > C9maxstr){
702 c->error("s9error: invalid ename: %ud chars", len);690 c->error(c, "s9error: invalid ename: %ud chars", len);
703 return C9Estr;691 return C9Estr;
704 }692 }
705 if((b = R(c, 2+len, Rerror, tag, &err)) != NULL){693 if((b = R(c, 2+len, Rerror, tag, &err)) != NULL){
@@ -743,7 +731,7 @@ s9walk(C9ctx *c, C9tag tag, C9qid *qids[]) · 37 unmodified lines
743 731
744 for(n = 0; n < C9maxpathel && qids[n] != NULL; n++);732 for(n = 0; n < C9maxpathel && qids[n] != NULL; n++);
745 if(n > C9maxpathel){733 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);
747 return C9Epath;735 return C9Epath;
748 }736 }
749 737
@@ -839,13 +827,13 @@ s9readdir(C9ctx *c, C9tag tag, C9stat *st[], int *num, uint64_t *offset, uint32_ · 89 unmodified lines
839 mulen = safestrlen(s->muid);827 mulen = safestrlen(s->muid);
840 828
841 if(nlen == 0 || nlen > C9maxstr){829 if(nlen == 0 || nlen > C9maxstr){
842 c->error("s9readdir: invalid name: %ud chars", nlen);830 c->error(c, "s9readdir: invalid name: %ud chars", nlen);
843 return C9Epath;831 return C9Epath;
844 }832 }
845 if(ulen > C9maxstr || glen > C9maxstr || mulen > C9maxstr){833 if(ulen > C9maxstr || glen > C9maxstr || mulen > C9maxstr){
846 ulen = ulen > glen ? ulen : glen;834 ulen = ulen > glen ? ulen : glen;
847 ulen = ulen > mulen ? ulen : mulen;835 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);
849 return C9Estr;837 return C9Estr;
850 }838 }
851 839
@@ -916,13 +904,13 @@ s9stat(C9ctx *c, C9tag tag, const C9stat *s) · 64 unmodified lines
916 C9error err;904 C9error err;
917 905
918 if(nlen == 0 || nlen > C9maxstr){906 if(nlen == 0 || nlen > C9maxstr){
919 c->error("s9stat: invalid name: %ud chars", nlen);907 c->error(c, "s9stat: invalid name: %ud chars", nlen);
920 return C9Epath;908 return C9Epath;
921 }909 }
922 if(ulen > C9maxstr || glen > C9maxstr || mulen > C9maxstr){910 if(ulen > C9maxstr || glen > C9maxstr || mulen > C9maxstr){
923 ulen = ulen > glen ? ulen : glen;911 ulen = ulen > glen ? ulen : glen;
924 ulen = ulen > mulen ? ulen : mulen;912 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);
926 return C9Estr;914 return C9Estr;
927 }915 }
928 916
@@ -969,20 +957,20 @@ s9proc(C9ctx *c) · 40 unmodified lines
969 readerr = -1;957 readerr = -1;
970 if((b = c->read(c, 4, &readerr)) == NULL){958 if((b = c->read(c, 4, &readerr)) == NULL){
971 if(readerr != 0)959 if(readerr != 0)
972 c->error("s9proc: short read");960 c->error(c, "s9proc: short read");
973 return readerr == 0 ? 0 : C9Epkt;961 return readerr == 0 ? 0 : C9Epkt;
974 }962 }
975 963
976 sz = r32(&b);964 sz = r32(&b);
977 if(sz < 7 || sz > c->msize){965 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);
979 return C9Epkt;967 return C9Epkt;
980 }968 }
981 sz -= 4;969 sz -= 4;
982 readerr = -1;970 readerr = -1;
983 if((b = c->read(c, sz, &readerr)) == NULL){971 if((b = c->read(c, sz, &readerr)) == NULL){
984 if(readerr != 0)972 if(readerr != 0)
985 c->error("s9proc: short read");973 c->error(c, "s9proc: short read");
986 return readerr == 0 ? 0 : C9Epkt;974 return readerr == 0 ? 0 : C9Epkt;
987 }975 }
988 976
@@ -991,7 +979,7 @@ s9proc(C9ctx *c) · 2 unmodified lines
991 sz -= 3;979 sz -= 3;
992 980
993 if((c->svflags & Svver) == 0 && t.type != Tversion){981 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);
995 return C9Epkt;983 return C9Epkt;
996 }984 }
997 985
@@ -1035,7 +1023,7 @@ s9proc(C9ctx *c) · 37 unmodified lines
1035 t.fid = r32(&b);1023 t.fid = r32(&b);
1036 t.walk.newfid = r32(&b);1024 t.walk.newfid = r32(&b);
1037 if((n = r16(&b)) > 16){1025 if((n = r16(&b)) > 16){
1038 c->error("s9proc: Twalk !(%ud <= 16)", n);1026 c->error(c, "s9proc: Twalk !(%ud <= 16)", n);
1039 return C9Epath;1027 return C9Epath;
1040 }1028 }
1041 sz -= 4+4+2;1029 sz -= 4+4+2;
@@ -1044,7 +1032,7 @@ s9proc(C9ctx *c) · 2 unmodified lines
1044 if(sz < 2 || (cnt = r16(&b)) > sz-2)1032 if(sz < 2 || (cnt = r16(&b)) > sz-2)
1045 goto error;1033 goto error;
1046 if(cnt < 1){1034 if(cnt < 1){
1047 c->error("s9proc: Twalk invalid element [%ud]", i);1035 c->error(c, "s9proc: Twalk invalid element [%ud]", i);
1048 return C9Epath;1036 return C9Epath;
1049 }1037 }
1050 b[-2] = 0;1038 b[-2] = 0;
@@ -1076,7 +1064,7 @@ s9proc(C9ctx *c) · 25 unmodified lines
1076 if((cnt = r16(&b)) > sz-4)1064 if((cnt = r16(&b)) > sz-4)
1077 goto error;1065 goto error;
1078 if((err = c9parsedir(c, &t.wstat, &b, &cnt)) != 0){1066 if((err = c9parsedir(c, &t.wstat, &b, &cnt)) != 0){
1079 c->error("s9proc");1067 c->error(c, "s9proc");
1080 return err;1068 return err;
1081 }1069 }
1082 c->t(c, &t);1070 c->t(c, &t);
@@ -1111,7 +1099,7 @@ s9proc(C9ctx *c) · 28 unmodified lines
1111 w32(&b, 0);1099 w32(&b, 0);
1112 wcs(&b, "unknown", 7);1100 wcs(&b, "unknown", 7);
1113 err = c->end(c);1101 err = c->end(c);
1114 c->error("s9proc: invalid version");1102 c->error(c, "s9proc: invalid version");
1115 }1103 }
1116 return C9Ever;1104 return C9Ever;
1117 }1105 }
@@ -1169,7 +1157,7 @@ s9proc(C9ctx *c) · 51 unmodified lines
1169 }1157 }
1170 return 0;1158 return 0;
1171error:1159error:
1172 c->error("s9proc: invalid packet (type=%ud)", t.type);1160 c->error(c, "s9proc: invalid packet (type=%ud)", t.type);
1173 return C9Epkt;1161 return C9Epkt;
1174}1162}
1175 1163

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