xref: /plan9-contrib/sys/src/cmd/aquarela/smbbuffer.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include "headers.h"
2 
3 #define BUFFER 1
4 #define STRUCT 2
5 #define PUSHED 4
6 
7 struct SmbBuffer {
8 	uchar *buf;
9 	ulong realmaxlen;
10 	ulong maxlen;
11 	ulong rn;
12 	ulong wn;
13 	ulong savewn;
14 	int flags;
15 };
16 
17 void
18 smbbufferreset(SmbBuffer *s)
19 {
20 	if (s == nil)
21 		return;
22 	s->rn = 0;
23 	s->wn = 0;
24 	s->flags &= ~PUSHED;
25 }
26 
27 void
28 smbbuffersetbuf(SmbBuffer *s, void *p, ulong maxlen)
29 {
30 	s->realmaxlen = s->maxlen = maxlen;
31 	if (s->buf) {
32 		if (s->flags & BUFFER)
33 			free(s->buf);
34 		s->buf = nil;
35 	}
36 	s->flags &= ~BUFFER;
37 	if (p)
38 		s->buf = p;
39 	else {
40 		s->buf = smbemalloc(maxlen);
41 		s->flags |= BUFFER;
42 	}
43 	smbbufferreset(s);
44 }
45 
46 SmbBuffer *
47 smbbufferinit(void *base, void *bdata, ulong blen)
48 {
49 	SmbBuffer *b;
50 	b = smbemalloc(sizeof(*b));
51 	b->buf = base;
52 	b->flags = STRUCT;
53 	b->rn = (uchar *)bdata - (uchar *)base;
54 	b->wn = b->rn + blen;
55 	b->realmaxlen = b->maxlen = b->wn;
56 	return b;
57 }
58 
59 int
60 smbbufferalignl2(SmbBuffer *s, int al2)
61 {
62 	ulong mask, newn;
63 	mask = (1 << al2) - 1;
64 	newn = (s->wn + mask) & ~mask;
65 	if (newn != s->wn) {
66 		if (newn > s->maxlen)
67 			return 0;
68 		s->wn = newn;
69 	}
70 	return 1;
71 }
72 
73 int
74 smbbufferputb(SmbBuffer *s, uchar b)
75 {
76 	if (s->wn >= s->maxlen)
77 		return 0;
78 	s->buf[s->wn++] = b;
79 	return 1;
80 }
81 
82 ulong
83 smbbufferspace(SmbBuffer *sess)
84 {
85 	return sess->maxlen - sess->wn;
86 }
87 
88 int
89 smbbufferoffsetputs(SmbBuffer *sess, ulong offset, ushort s)
90 {
91 	if (offset + 2 > sess->wn)
92 		return 0;
93 	smbhnputs(sess->buf + offset, s);
94 	return 1;
95 }
96 
97 int
98 smbbufferputs(SmbBuffer *sess, ushort s)
99 {
100 	if (sess->wn + sizeof(ushort) > sess->maxlen)
101 		return 0;
102 	smbhnputs(sess->buf + sess->wn, s);
103 	sess->wn += sizeof(ushort);
104 	return 1;
105 }
106 
107 int
108 smbbufferputl(SmbBuffer *s, ulong l)
109 {
110 	if (s->wn + sizeof(ulong) > s->maxlen)
111 		return 0;
112 	smbhnputl(s->buf + s->wn, l);
113 	s->wn += sizeof(ulong);
114 	return 1;
115 }
116 
117 int
118 smbbufferputv(SmbBuffer *s, vlong v)
119 {
120 	if (s->wn + sizeof(vlong) > s->maxlen)
121 		return 0;
122 	smbhnputv(s->buf + s->wn, v);
123 	s->wn += sizeof(vlong);
124 	return 1;
125 }
126 
127 int
128 smbbufferputbytes(SmbBuffer *s, void *data, ulong datalen)
129 {
130 	if (s->wn + datalen > s->maxlen)
131 		return 0;
132 	if (data)
133 		memcpy(s->buf + s->wn, data, datalen);
134 	s->wn += datalen;
135 	return 1;
136 }
137 
138 int
139 smbbufferputstring(SmbBuffer *b, SmbPeerInfo *p, ulong flags, char *string)
140 {
141 	int n = smbstringput(p, flags, b->buf, b->wn, b->maxlen, string);
142 	if (n <= 0)
143 		return 0;
144 	b->wn += n;
145 	return 1;
146 }
147 
148 int
149 smbbufferputstrn(SmbBuffer *s, char *string, int size, int upcase)
150 {
151 	int n = smbstrnput(s->buf, s->wn, s->maxlen, string, size, upcase);
152 	if (n <= 0)
153 		return 0;
154 	s->wn += n;
155 	return 1;
156 }
157 
158 ulong
159 smbbufferwriteoffset(SmbBuffer *s)
160 {
161 	return s->wn;
162 }
163 
164 ulong
165 smbbufferwritemaxoffset(SmbBuffer *s)
166 {
167 	return s->maxlen;
168 }
169 
170 ulong
171 smbbufferreadoffset(SmbBuffer *s)
172 {
173 	return s->rn;
174 }
175 
176 void *
177 smbbufferreadpointer(SmbBuffer *s)
178 {
179 	return s->buf + s->rn;
180 }
181 
182 void *
183 smbbufferwritepointer(SmbBuffer *s)
184 {
185 	return s->buf + s->wn;
186 }
187 
188 ulong
189 smbbufferwritespace(SmbBuffer *b)
190 {
191 	return b->maxlen - b->wn;
192 }
193 
194 SmbBuffer *
195 smbbuffernew(ulong maxlen)
196 {
197 	SmbBuffer *b;
198 	b = smbemalloc(sizeof(SmbBuffer));
199 	b->buf = smbemalloc(maxlen);
200 	b->realmaxlen = b->maxlen = maxlen;
201 	b->rn = 0;
202 	b->wn = 0;
203 	b->flags = STRUCT | BUFFER;
204 	return b;
205 }
206 
207 void
208 smbbufferfree(SmbBuffer **bp)
209 {
210 	SmbBuffer *b = *bp;
211 	if (b) {
212 		if (b->flags & BUFFER) {
213 			free(b->buf);
214 			b->buf = nil;
215 			b->flags &= ~BUFFER;
216 		}
217 		if (b->flags & STRUCT)
218 			free(b);
219 		*bp = nil;
220 	}
221 }
222 
223 uchar *
224 smbbufferbase(SmbBuffer *b)
225 {
226 	return b->buf;
227 }
228 
229 int
230 smbbuffergetbytes(SmbBuffer *b, void *buf, ulong len)
231 {
232 	if (b->rn + len > b->wn)
233 		return 0;
234 	if (buf)
235 		memcpy(buf, b->buf + b->rn, len);
236 	b->rn += len;
237 	return 1;
238 }
239 
240 void
241 smbbuffersetreadlen(SmbBuffer *b, ulong len)
242 {
243 	b->wn = b->rn + len;
244 }
245 
246 int
247 smbbuffertrimreadlen(SmbBuffer *b, ulong len)
248 {
249 	if (b->rn + len > b->wn)
250 		return 0;
251 	else if (b->rn + len < b->wn)
252 		b->wn = b->rn + len;
253 	return 1;
254 }
255 
256 int
257 smbbuffergets(SmbBuffer *b, ushort *sp)
258 {
259 	if (b->rn + 2 > b->wn)
260 		return 0;
261 	*sp = smbnhgets(b->buf + b->rn);
262 	b->rn += 2;
263 	return 1;
264 }
265 
266 int
267 smbbuffergetstrn(SmbBuffer *b, ushort size, char **sp)
268 {
269 	uchar *np;
270 	if (size > b->wn - b->rn)
271 		return 0;
272 	np = memchr(b->buf + b->rn, 0, size);
273 	if (np == nil)
274 		return 0;
275 	*sp = strdup((char *)b->buf + b->rn);
276 	b->rn += size;
277 	return 1;
278 }
279 
280 int
281 smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp)
282 {
283 	uchar *np;
284 	USED(flags);
285 	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
286 	if (np == nil)
287 		return 0;
288 	*sp = strdup((char *)b->buf + b->rn);
289 	b->rn = np - b->buf + 1;
290 	return 1;
291 }
292 
293 int
294 smbbuffergetstrinline(SmbBuffer *b, char **sp)
295 {
296 	uchar *np;
297 	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
298 	if (np == nil)
299 		return 0;
300 	*sp = (char *)b->buf + b->rn;
301 	b->rn = np - b->buf + 1;
302 	return 1;
303 }
304 
305 int
306 smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp)
307 {
308 	uchar *bdata = b->buf + b->rn;
309 	uchar *edata = b->buf + b->wn;
310 	Rune r;
311 	int l;
312 	char *p, *q;
313 	uchar *savebdata;
314 	int first;
315 
316 	l = 0;
317 	if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1)
318 		bdata++;
319 	savebdata = bdata;
320 	first = 1;
321 	do {
322 		if (bdata + 2 > edata) {
323 			l++;
324 			break;
325 		}
326 		r = smbnhgets(bdata); bdata += 2;
327 		if (first && (flags & SMB_STRING_PATH) && r != '\\')
328 			l++;
329 		first = 0;
330 		if (flags & SMB_STRING_CONVERT_MASK)
331 			r = smbruneconvert(r, flags);
332 		l += runelen(r);
333 	} while (r != 0);
334 	p = smbemalloc(l);
335 	bdata = savebdata;
336 	q = p;
337 	first = 1;
338 	do {
339 		if (bdata + 2 > edata) {
340 			*q = 0;
341 			break;
342 		}
343 		r = smbnhgets(bdata); bdata += 2;
344 		if (first && (flags & SMB_STRING_PATH) && r != '\\')
345 			*q++ = '/';
346 		first = 0;
347 		if (flags & SMB_STRING_CONVERT_MASK)
348 			r = smbruneconvert(r, flags);
349 		q += runetochar(q, &r);
350 	} while (r != 0);
351 	b->rn = bdata - b->buf;
352 	*sp = p;
353 	return 1;
354 }
355 
356 int
357 smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp)
358 {
359 	if (flags & SMB_STRING_UNICODE)
360 		return smbbuffergetucs2(b, flags, sp);
361 	else if (flags & SMB_STRING_ASCII)
362 		return smbbuffergetstr(b, flags, sp);
363 	else if (h->flags2 & SMB_FLAGS2_UNICODE)
364 		return smbbuffergetucs2(b, flags, sp);
365 	else
366 		return smbbuffergetstr(b, flags, sp);
367 }
368 
369 void *
370 smbbufferpointer(SmbBuffer *b, ulong offset)
371 {
372 	return b->buf + offset;
373 }
374 
375 int
376 smbbuffergetb(SmbBuffer *b, uchar *bp)
377 {
378 	if (b->rn < b->wn) {
379 		*bp = b->buf[b->rn++];
380 		return 1;
381 	}
382 	return 0;
383 }
384 
385 int
386 smbbuffergetl(SmbBuffer *b, ulong *lp)
387 {
388 	if (b->rn + 4 <= b->wn) {
389 		*lp = smbnhgetl(b->buf + b->rn);
390 		b->rn += 4;
391 		return 1;
392 	}
393 	return 0;
394 }
395 
396 int
397 smbbuffergetv(SmbBuffer *b, vlong *vp)
398 {
399 	if (b->rn + 8 <= b->wn) {
400 		*vp = smbnhgetv(b->buf + b->rn);
401 		b->rn += 8;
402 		return 1;
403 	}
404 	return 0;
405 }
406 
407 ulong
408 smbbufferreadspace(SmbBuffer *b)
409 {
410 	return b->wn - b->rn;
411 }
412 
413 void
414 smbbufferwritelimit(SmbBuffer *b, ulong limit)
415 {
416 	if (b->rn + limit < b->maxlen)
417 		b->maxlen = b->rn + limit;
418 }
419 
420 int
421 smbbufferreadskipto(SmbBuffer *b, ulong offset)
422 {
423 	if (offset < b->rn || offset >= b->wn)
424 		return 0;
425 	b->rn = offset;
426 	return 1;
427 }
428 
429 int
430 smbbufferpushreadlimit(SmbBuffer *b, ulong limit)
431 {
432 	if (b->flags & PUSHED)
433 		return 0;
434 	if (limit > b->wn || limit < b->rn)
435 		return 0;
436 	b->savewn = b->wn;
437 	b->wn = limit;
438 	b->flags |= PUSHED;
439 	return 1;
440 }
441 
442 int
443 smbbufferpopreadlimit(SmbBuffer *b)
444 {
445 	if ((b->flags & PUSHED) == 0)
446 		return 0;
447 	b->wn = b->savewn;
448 	b->flags &= ~PUSHED;
449 	return 1;
450 }
451 
452 int
453 smbbufferwritebackup(SmbBuffer *b, ulong offset)
454 {
455 	if (offset >= b->rn && offset <= b->wn) {
456 		b->wn = offset;
457 		return 1;
458 	}
459 	return 0;
460 }
461 
462 int
463 smbbufferreadbackup(SmbBuffer *b, ulong offset)
464 {
465 	if (offset <= b->rn) {
466 		b->rn = offset;
467 		return 1;
468 	}
469 	return 0;
470 }
471 
472 int
473 smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset)
474 {
475 	ulong fixval;
476 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
477 		return 0;
478 	fixval = b->wn - fixupoffset - 2;
479 	if (fixval > 65535)
480 		return 0;
481 	smbhnputs(b->buf + fixupoffset, fixval);
482 	return 1;
483 }
484 
485 int
486 smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset)
487 {
488 	ulong fixval;
489 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
490 		return 0;
491 	fixval = b->wn - fixupoffset - 4;
492 	smbhnputl(b->buf + fixupoffset, fixval);
493 	return 1;
494 }
495 
496 int
497 smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset)
498 {
499 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
500 		return 0;
501 	if (b->wn > 65535)
502 		return 0;
503 	smbhnputs(b->buf + fixupoffset, b->wn);
504 	return 1;
505 }
506 
507 int
508 smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong fixupval)
509 {
510 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
511 		return 0;
512 	smbhnputl(b->buf + fixupoffset, fixupval);
513 	return 1;
514 }
515 
516 int
517 smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset)
518 {
519 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
520 		return 0;
521 	smbhnputl(b->buf + fixupoffset, b->wn);
522 	return 1;
523 }
524 
525 int
526 smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset)
527 {
528 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
529 		return 0;
530 	smbhnputl(b->buf + fixupoffset, b->wn - fixupoffset);
531 	return 1;
532 }
533 
534 int
535 smbbufferfill(SmbBuffer *b, uchar val, ulong len)
536 {
537 	if (b->maxlen - b->wn < len)
538 		return 0;
539 	memset(b->buf + b->wn, val, len);
540 	b->wn += len;
541 	return 1;
542 }
543 
544 int
545 smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp)
546 {
547 	if (offset >= b->rn && offset + 1 <= b->wn) {
548 		*bp = b->buf[b->rn + offset];
549 		return 1;
550 	}
551 	return 0;
552 }
553 
554 int
555 smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount)
556 {
557 	if (smbbufferreadspace(from) < amount)
558 		return 0;
559 	if (smbbufferputbytes(to, smbbufferreadpointer(from), amount)) {
560 		assert(smbbuffergetbytes(from, nil, amount));
561 		return 1;
562 	}
563 	return 0;
564 }
565 
566 int
567 smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp)
568 {
569 	uchar *np;
570 	if (offset < b->rn || offset >= b->wn)
571 		return 0;
572 	np = memchr(b->buf + offset, 0, b->wn - offset);
573 	if (np == nil)
574 		return 0;
575 	*lenp = np - (b->buf + offset) + 1;
576 	if (*lenp > buflen)
577 		return 0;
578 	memcpy(buf, b->buf + offset, *lenp);
579 	return 1;
580 }
581