xref: /plan9/sys/src/cmd/aquarela/smbbuffer.c (revision b698dcfadb276a6209fd40d3fd699dab70955a1b)
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
smbbufferreset(SmbBuffer * s)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
smbbuffersetbuf(SmbBuffer * s,void * p,ulong maxlen)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 *
smbbufferinit(void * base,void * bdata,ulong blen)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
smbbufferalignl2(SmbBuffer * s,int al2)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
smbbufferputb(SmbBuffer * s,uchar b)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
smbbufferspace(SmbBuffer * sess)83 smbbufferspace(SmbBuffer *sess)
84 {
85 	return sess->maxlen - sess->wn;
86 }
87 
88 int
smbbufferoffsetputs(SmbBuffer * sess,ulong offset,ushort s)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
smbbufferputs(SmbBuffer * sess,ushort s)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
smbbufferputl(SmbBuffer * s,ulong l)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
smbbufferputv(SmbBuffer * s,vlong v)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
smbbufferputbytes(SmbBuffer * s,void * data,ulong datalen)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
smbbufferputstring(SmbBuffer * b,SmbPeerInfo * p,ulong flags,char * string)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
smbbufferputstrn(SmbBuffer * s,char * string,int size,int upcase)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
smbbufferwriteoffset(SmbBuffer * s)159 smbbufferwriteoffset(SmbBuffer *s)
160 {
161 	return s->wn;
162 }
163 
164 ulong
smbbufferwritemaxoffset(SmbBuffer * s)165 smbbufferwritemaxoffset(SmbBuffer *s)
166 {
167 	return s->maxlen;
168 }
169 
170 ulong
smbbufferreadoffset(SmbBuffer * s)171 smbbufferreadoffset(SmbBuffer *s)
172 {
173 	return s->rn;
174 }
175 
176 void *
smbbufferreadpointer(SmbBuffer * s)177 smbbufferreadpointer(SmbBuffer *s)
178 {
179 	return s->buf + s->rn;
180 }
181 
182 void *
smbbufferwritepointer(SmbBuffer * s)183 smbbufferwritepointer(SmbBuffer *s)
184 {
185 	return s->buf + s->wn;
186 }
187 
188 ulong
smbbufferwritespace(SmbBuffer * b)189 smbbufferwritespace(SmbBuffer *b)
190 {
191 	return b->maxlen - b->wn;
192 }
193 
194 SmbBuffer *
smbbuffernew(ulong maxlen)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
smbbufferfree(SmbBuffer ** bp)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 *
smbbufferbase(SmbBuffer * b)224 smbbufferbase(SmbBuffer *b)
225 {
226 	return b->buf;
227 }
228 
229 int
smbbuffergetbytes(SmbBuffer * b,void * buf,ulong len)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
smbbuffersetreadlen(SmbBuffer * b,ulong len)241 smbbuffersetreadlen(SmbBuffer *b, ulong len)
242 {
243 	b->wn = b->rn + len;
244 }
245 
246 int
smbbuffertrimreadlen(SmbBuffer * b,ulong len)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
smbbuffergets(SmbBuffer * b,ushort * sp)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
smbbuffergetstrn(SmbBuffer * b,ushort size,char ** sp)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
smbbuffergetstr(SmbBuffer * b,ulong flags,char ** sp)281 smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp)
282 {
283 	int c;
284 	char *p;
285 	uchar *np;
286 
287 	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
288 	if (np == nil)
289 		return 0;
290 	*sp = strdup((char *)b->buf + b->rn);
291 	for (p = *sp; *p != 0; p++) {
292 		c = *p;
293 		if (c >= 'a' && c <= 'z' && (flags & SMB_STRING_UPCASE))
294 			*p = toupper(c);
295 		else if (c == '/' && (flags & SMB_STRING_REVPATH))
296 			*p = '\\';
297 		else if (c == '\\' && (flags & SMB_STRING_PATH))
298 			*p = '/';
299 		else if (smbglobals.convertspace){
300 			if (c == 0xa0 && (flags & SMB_STRING_REVPATH))
301 				*p = ' ';
302 			else if (c == ' ' && (flags & SMB_STRING_PATH))
303 				*p = 0xa0;
304 		}
305 	}
306 	b->rn = np - b->buf + 1;
307 	return 1;
308 }
309 
310 int
smbbuffergetstrinline(SmbBuffer * b,char ** sp)311 smbbuffergetstrinline(SmbBuffer *b, char **sp)
312 {
313 	uchar *np;
314 	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
315 	if (np == nil)
316 		return 0;
317 	*sp = (char *)b->buf + b->rn;
318 	b->rn = np - b->buf + 1;
319 	return 1;
320 }
321 
322 int
smbbuffergetucs2(SmbBuffer * b,ulong flags,char ** sp)323 smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp)
324 {
325 	uchar *bdata = b->buf + b->rn;
326 	uchar *edata = b->buf + b->wn;
327 	Rune r;
328 	int l;
329 	char *p, *q;
330 	uchar *savebdata;
331 	int first;
332 
333 	l = 0;
334 	if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1)
335 		bdata++;
336 	savebdata = bdata;
337 	first = 1;
338 	do {
339 		if (bdata + 2 > edata) {
340 			l++;
341 			break;
342 		}
343 		r = smbnhgets(bdata); bdata += 2;
344 		if (first && (flags & SMB_STRING_PATH) && r != '\\')
345 			l++;
346 		first = 0;
347 		if (flags & SMB_STRING_CONVERT_MASK)
348 			r = smbruneconvert(r, flags);
349 		l += runelen(r);
350 	} while (r != 0);
351 	p = smbemalloc(l);
352 	bdata = savebdata;
353 	q = p;
354 	first = 1;
355 	do {
356 		if (bdata + 2 > edata) {
357 			*q = 0;
358 			break;
359 		}
360 		r = smbnhgets(bdata); bdata += 2;
361 		if (first && (flags & SMB_STRING_PATH) && r != '\\')
362 			*q++ = '/';
363 		first = 0;
364 		if (flags & SMB_STRING_CONVERT_MASK)
365 			r = smbruneconvert(r, flags);
366 		q += runetochar(q, &r);
367 	} while (r != 0);
368 	b->rn = bdata - b->buf;
369 	*sp = p;
370 	return 1;
371 }
372 
373 int
smbbuffergetstring(SmbBuffer * b,SmbHeader * h,ulong flags,char ** sp)374 smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp)
375 {
376 	if (flags & SMB_STRING_UNICODE)
377 		return smbbuffergetucs2(b, flags, sp);
378 	else if (flags & SMB_STRING_ASCII)
379 		return smbbuffergetstr(b, flags, sp);
380 	else if (h->flags2 & SMB_FLAGS2_UNICODE)
381 		return smbbuffergetucs2(b, flags, sp);
382 	else
383 		return smbbuffergetstr(b, flags, sp);
384 }
385 
386 void *
smbbufferpointer(SmbBuffer * b,ulong offset)387 smbbufferpointer(SmbBuffer *b, ulong offset)
388 {
389 	return b->buf + offset;
390 }
391 
392 int
smbbuffergetb(SmbBuffer * b,uchar * bp)393 smbbuffergetb(SmbBuffer *b, uchar *bp)
394 {
395 	if (b->rn < b->wn) {
396 		*bp = b->buf[b->rn++];
397 		return 1;
398 	}
399 	return 0;
400 }
401 
402 int
smbbuffergetl(SmbBuffer * b,ulong * lp)403 smbbuffergetl(SmbBuffer *b, ulong *lp)
404 {
405 	if (b->rn + 4 <= b->wn) {
406 		*lp = smbnhgetl(b->buf + b->rn);
407 		b->rn += 4;
408 		return 1;
409 	}
410 	return 0;
411 }
412 
413 int
smbbuffergetv(SmbBuffer * b,vlong * vp)414 smbbuffergetv(SmbBuffer *b, vlong *vp)
415 {
416 	if (b->rn + 8 <= b->wn) {
417 		*vp = smbnhgetv(b->buf + b->rn);
418 		b->rn += 8;
419 		return 1;
420 	}
421 	return 0;
422 }
423 
424 ulong
smbbufferreadspace(SmbBuffer * b)425 smbbufferreadspace(SmbBuffer *b)
426 {
427 	return b->wn - b->rn;
428 }
429 
430 void
smbbufferwritelimit(SmbBuffer * b,ulong limit)431 smbbufferwritelimit(SmbBuffer *b, ulong limit)
432 {
433 	if (b->rn + limit < b->maxlen)
434 		b->maxlen = b->rn + limit;
435 }
436 
437 int
smbbufferreadskipto(SmbBuffer * b,ulong offset)438 smbbufferreadskipto(SmbBuffer *b, ulong offset)
439 {
440 	if (offset < b->rn || offset >= b->wn)
441 		return 0;
442 	b->rn = offset;
443 	return 1;
444 }
445 
446 int
smbbufferpushreadlimit(SmbBuffer * b,ulong limit)447 smbbufferpushreadlimit(SmbBuffer *b, ulong limit)
448 {
449 	if (b->flags & PUSHED)
450 		return 0;
451 	if (limit > b->wn || limit < b->rn)
452 		return 0;
453 	b->savewn = b->wn;
454 	b->wn = limit;
455 	b->flags |= PUSHED;
456 	return 1;
457 }
458 
459 int
smbbufferpopreadlimit(SmbBuffer * b)460 smbbufferpopreadlimit(SmbBuffer *b)
461 {
462 	if ((b->flags & PUSHED) == 0)
463 		return 0;
464 	b->wn = b->savewn;
465 	b->flags &= ~PUSHED;
466 	return 1;
467 }
468 
469 int
smbbufferwritebackup(SmbBuffer * b,ulong offset)470 smbbufferwritebackup(SmbBuffer *b, ulong offset)
471 {
472 	if (offset >= b->rn && offset <= b->wn) {
473 		b->wn = offset;
474 		return 1;
475 	}
476 	return 0;
477 }
478 
479 int
smbbufferreadbackup(SmbBuffer * b,ulong offset)480 smbbufferreadbackup(SmbBuffer *b, ulong offset)
481 {
482 	if (offset <= b->rn) {
483 		b->rn = offset;
484 		return 1;
485 	}
486 	return 0;
487 }
488 
489 int
smbbufferfixuprelatives(SmbBuffer * b,ulong fixupoffset)490 smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset)
491 {
492 	ulong fixval;
493 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
494 		return 0;
495 	fixval = b->wn - fixupoffset - 2;
496 	if (fixval > 65535)
497 		return 0;
498 	smbhnputs(b->buf + fixupoffset, fixval);
499 	return 1;
500 }
501 
502 int
smbbufferfixuprelativel(SmbBuffer * b,ulong fixupoffset)503 smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset)
504 {
505 	ulong fixval;
506 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
507 		return 0;
508 	fixval = b->wn - fixupoffset - 4;
509 	smbhnputl(b->buf + fixupoffset, fixval);
510 	return 1;
511 }
512 
513 int
smbbufferfixupabsolutes(SmbBuffer * b,ulong fixupoffset)514 smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset)
515 {
516 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
517 		return 0;
518 	if (b->wn > 65535)
519 		return 0;
520 	smbhnputs(b->buf + fixupoffset, b->wn);
521 	return 1;
522 }
523 
524 int
smbbufferfixupl(SmbBuffer * b,ulong fixupoffset,ulong fixupval)525 smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong fixupval)
526 {
527 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
528 		return 0;
529 	smbhnputl(b->buf + fixupoffset, fixupval);
530 	return 1;
531 }
532 
533 int
smbbufferfixupabsolutel(SmbBuffer * b,ulong fixupoffset)534 smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset)
535 {
536 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
537 		return 0;
538 	smbhnputl(b->buf + fixupoffset, b->wn);
539 	return 1;
540 }
541 
542 int
smbbufferfixuprelativeinclusivel(SmbBuffer * b,ulong fixupoffset)543 smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset)
544 {
545 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
546 		return 0;
547 	smbhnputl(b->buf + fixupoffset, b->wn - fixupoffset);
548 	return 1;
549 }
550 
551 int
smbbufferfill(SmbBuffer * b,uchar val,ulong len)552 smbbufferfill(SmbBuffer *b, uchar val, ulong len)
553 {
554 	if (b->maxlen - b->wn < len)
555 		return 0;
556 	memset(b->buf + b->wn, val, len);
557 	b->wn += len;
558 	return 1;
559 }
560 
561 int
smbbufferoffsetgetb(SmbBuffer * b,ulong offset,uchar * bp)562 smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp)
563 {
564 	if (offset >= b->rn && offset + 1 <= b->wn) {
565 		*bp = b->buf[b->rn + offset];
566 		return 1;
567 	}
568 	return 0;
569 }
570 
571 int
smbbuffercopy(SmbBuffer * to,SmbBuffer * from,ulong amount)572 smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount)
573 {
574 	if (smbbufferreadspace(from) < amount)
575 		return 0;
576 	if (smbbufferputbytes(to, smbbufferreadpointer(from), amount)) {
577 		assert(smbbuffergetbytes(from, nil, amount));
578 		return 1;
579 	}
580 	return 0;
581 }
582 
583 int
smbbufferoffsetcopystr(SmbBuffer * b,ulong offset,char * buf,int buflen,int * lenp)584 smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp)
585 {
586 	uchar *np;
587 	if (offset < b->rn || offset >= b->wn)
588 		return 0;
589 	np = memchr(b->buf + offset, 0, b->wn - offset);
590 	if (np == nil)
591 		return 0;
592 	*lenp = np - (b->buf + offset) + 1;
593 	if (*lenp > buflen)
594 		return 0;
595 	memcpy(buf, b->buf + offset, *lenp);
596 	return 1;
597 }
598