xref: /plan9/sys/src/cmd/aquarela/smbbuffer.c (revision b698dcfadb276a6209fd40d3fd699dab70955a1b)
18ccd4a63SDavid du Colombier #include "headers.h"
28ccd4a63SDavid du Colombier 
38ccd4a63SDavid du Colombier #define BUFFER 1
48ccd4a63SDavid du Colombier #define STRUCT 2
58ccd4a63SDavid du Colombier #define PUSHED 4
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier struct SmbBuffer {
88ccd4a63SDavid du Colombier 	uchar *buf;
98ccd4a63SDavid du Colombier 	ulong realmaxlen;
108ccd4a63SDavid du Colombier 	ulong maxlen;
118ccd4a63SDavid du Colombier 	ulong rn;
128ccd4a63SDavid du Colombier 	ulong wn;
138ccd4a63SDavid du Colombier 	ulong savewn;
148ccd4a63SDavid du Colombier 	int flags;
158ccd4a63SDavid du Colombier };
168ccd4a63SDavid du Colombier 
178ccd4a63SDavid du Colombier void
smbbufferreset(SmbBuffer * s)188ccd4a63SDavid du Colombier smbbufferreset(SmbBuffer *s)
198ccd4a63SDavid du Colombier {
208ccd4a63SDavid du Colombier 	if (s == nil)
218ccd4a63SDavid du Colombier 		return;
228ccd4a63SDavid du Colombier 	s->rn = 0;
238ccd4a63SDavid du Colombier 	s->wn = 0;
248ccd4a63SDavid du Colombier 	s->flags &= ~PUSHED;
258ccd4a63SDavid du Colombier }
268ccd4a63SDavid du Colombier 
278ccd4a63SDavid du Colombier void
smbbuffersetbuf(SmbBuffer * s,void * p,ulong maxlen)288ccd4a63SDavid du Colombier smbbuffersetbuf(SmbBuffer *s, void *p, ulong maxlen)
298ccd4a63SDavid du Colombier {
308ccd4a63SDavid du Colombier 	s->realmaxlen = s->maxlen = maxlen;
318ccd4a63SDavid du Colombier 	if (s->buf) {
328ccd4a63SDavid du Colombier 		if (s->flags & BUFFER)
338ccd4a63SDavid du Colombier 			free(s->buf);
348ccd4a63SDavid du Colombier 		s->buf = nil;
358ccd4a63SDavid du Colombier 	}
368ccd4a63SDavid du Colombier 	s->flags &= ~BUFFER;
378ccd4a63SDavid du Colombier 	if (p)
388ccd4a63SDavid du Colombier 		s->buf = p;
398ccd4a63SDavid du Colombier 	else {
408ccd4a63SDavid du Colombier 		s->buf = smbemalloc(maxlen);
418ccd4a63SDavid du Colombier 		s->flags |= BUFFER;
428ccd4a63SDavid du Colombier 	}
438ccd4a63SDavid du Colombier 	smbbufferreset(s);
448ccd4a63SDavid du Colombier }
458ccd4a63SDavid du Colombier 
468ccd4a63SDavid du Colombier SmbBuffer *
smbbufferinit(void * base,void * bdata,ulong blen)478ccd4a63SDavid du Colombier smbbufferinit(void *base, void *bdata, ulong blen)
488ccd4a63SDavid du Colombier {
498ccd4a63SDavid du Colombier 	SmbBuffer *b;
508ccd4a63SDavid du Colombier 	b = smbemalloc(sizeof(*b));
518ccd4a63SDavid du Colombier 	b->buf = base;
528ccd4a63SDavid du Colombier 	b->flags = STRUCT;
538ccd4a63SDavid du Colombier 	b->rn = (uchar *)bdata - (uchar *)base;
548ccd4a63SDavid du Colombier 	b->wn = b->rn + blen;
558ccd4a63SDavid du Colombier 	b->realmaxlen = b->maxlen = b->wn;
568ccd4a63SDavid du Colombier 	return b;
578ccd4a63SDavid du Colombier }
588ccd4a63SDavid du Colombier 
598ccd4a63SDavid du Colombier int
smbbufferalignl2(SmbBuffer * s,int al2)608ccd4a63SDavid du Colombier smbbufferalignl2(SmbBuffer *s, int al2)
618ccd4a63SDavid du Colombier {
628ccd4a63SDavid du Colombier 	ulong mask, newn;
638ccd4a63SDavid du Colombier 	mask = (1 << al2) - 1;
648ccd4a63SDavid du Colombier 	newn = (s->wn + mask) & ~mask;
658ccd4a63SDavid du Colombier 	if (newn != s->wn) {
668ccd4a63SDavid du Colombier 		if (newn > s->maxlen)
678ccd4a63SDavid du Colombier 			return 0;
688ccd4a63SDavid du Colombier 		s->wn = newn;
698ccd4a63SDavid du Colombier 	}
708ccd4a63SDavid du Colombier 	return 1;
718ccd4a63SDavid du Colombier }
728ccd4a63SDavid du Colombier 
738ccd4a63SDavid du Colombier int
smbbufferputb(SmbBuffer * s,uchar b)748ccd4a63SDavid du Colombier smbbufferputb(SmbBuffer *s, uchar b)
758ccd4a63SDavid du Colombier {
768ccd4a63SDavid du Colombier 	if (s->wn >= s->maxlen)
778ccd4a63SDavid du Colombier 		return 0;
788ccd4a63SDavid du Colombier 	s->buf[s->wn++] = b;
798ccd4a63SDavid du Colombier 	return 1;
808ccd4a63SDavid du Colombier }
818ccd4a63SDavid du Colombier 
828ccd4a63SDavid du Colombier ulong
smbbufferspace(SmbBuffer * sess)838ccd4a63SDavid du Colombier smbbufferspace(SmbBuffer *sess)
848ccd4a63SDavid du Colombier {
858ccd4a63SDavid du Colombier 	return sess->maxlen - sess->wn;
868ccd4a63SDavid du Colombier }
878ccd4a63SDavid du Colombier 
888ccd4a63SDavid du Colombier int
smbbufferoffsetputs(SmbBuffer * sess,ulong offset,ushort s)898ccd4a63SDavid du Colombier smbbufferoffsetputs(SmbBuffer *sess, ulong offset, ushort s)
908ccd4a63SDavid du Colombier {
918ccd4a63SDavid du Colombier 	if (offset + 2 > sess->wn)
928ccd4a63SDavid du Colombier 		return 0;
938ccd4a63SDavid du Colombier 	smbhnputs(sess->buf + offset, s);
948ccd4a63SDavid du Colombier 	return 1;
958ccd4a63SDavid du Colombier }
968ccd4a63SDavid du Colombier 
978ccd4a63SDavid du Colombier int
smbbufferputs(SmbBuffer * sess,ushort s)988ccd4a63SDavid du Colombier smbbufferputs(SmbBuffer *sess, ushort s)
998ccd4a63SDavid du Colombier {
1008ccd4a63SDavid du Colombier 	if (sess->wn + sizeof(ushort) > sess->maxlen)
1018ccd4a63SDavid du Colombier 		return 0;
1028ccd4a63SDavid du Colombier 	smbhnputs(sess->buf + sess->wn, s);
1038ccd4a63SDavid du Colombier 	sess->wn += sizeof(ushort);
1048ccd4a63SDavid du Colombier 	return 1;
1058ccd4a63SDavid du Colombier }
1068ccd4a63SDavid du Colombier 
1078ccd4a63SDavid du Colombier int
smbbufferputl(SmbBuffer * s,ulong l)1088ccd4a63SDavid du Colombier smbbufferputl(SmbBuffer *s, ulong l)
1098ccd4a63SDavid du Colombier {
1108ccd4a63SDavid du Colombier 	if (s->wn + sizeof(ulong) > s->maxlen)
1118ccd4a63SDavid du Colombier 		return 0;
1128ccd4a63SDavid du Colombier 	smbhnputl(s->buf + s->wn, l);
1138ccd4a63SDavid du Colombier 	s->wn += sizeof(ulong);
1148ccd4a63SDavid du Colombier 	return 1;
1158ccd4a63SDavid du Colombier }
1168ccd4a63SDavid du Colombier 
1178ccd4a63SDavid du Colombier int
smbbufferputv(SmbBuffer * s,vlong v)1188ccd4a63SDavid du Colombier smbbufferputv(SmbBuffer *s, vlong v)
1198ccd4a63SDavid du Colombier {
1208ccd4a63SDavid du Colombier 	if (s->wn + sizeof(vlong) > s->maxlen)
1218ccd4a63SDavid du Colombier 		return 0;
1228ccd4a63SDavid du Colombier 	smbhnputv(s->buf + s->wn, v);
1238ccd4a63SDavid du Colombier 	s->wn += sizeof(vlong);
1248ccd4a63SDavid du Colombier 	return 1;
1258ccd4a63SDavid du Colombier }
1268ccd4a63SDavid du Colombier 
1278ccd4a63SDavid du Colombier int
smbbufferputbytes(SmbBuffer * s,void * data,ulong datalen)1288ccd4a63SDavid du Colombier smbbufferputbytes(SmbBuffer *s, void *data, ulong datalen)
1298ccd4a63SDavid du Colombier {
1308ccd4a63SDavid du Colombier 	if (s->wn + datalen > s->maxlen)
1318ccd4a63SDavid du Colombier 		return 0;
1328ccd4a63SDavid du Colombier 	if (data)
1338ccd4a63SDavid du Colombier 		memcpy(s->buf + s->wn, data, datalen);
1348ccd4a63SDavid du Colombier 	s->wn += datalen;
1358ccd4a63SDavid du Colombier 	return 1;
1368ccd4a63SDavid du Colombier }
1378ccd4a63SDavid du Colombier 
1388ccd4a63SDavid du Colombier int
smbbufferputstring(SmbBuffer * b,SmbPeerInfo * p,ulong flags,char * string)1398ccd4a63SDavid du Colombier smbbufferputstring(SmbBuffer *b, SmbPeerInfo *p, ulong flags, char *string)
1408ccd4a63SDavid du Colombier {
1418ccd4a63SDavid du Colombier 	int n = smbstringput(p, flags, b->buf, b->wn, b->maxlen, string);
1428ccd4a63SDavid du Colombier 	if (n <= 0)
1438ccd4a63SDavid du Colombier 		return 0;
1448ccd4a63SDavid du Colombier 	b->wn += n;
1458ccd4a63SDavid du Colombier 	return 1;
1468ccd4a63SDavid du Colombier }
1478ccd4a63SDavid du Colombier 
1488ccd4a63SDavid du Colombier int
smbbufferputstrn(SmbBuffer * s,char * string,int size,int upcase)1498ccd4a63SDavid du Colombier smbbufferputstrn(SmbBuffer *s, char *string, int size, int upcase)
1508ccd4a63SDavid du Colombier {
1518ccd4a63SDavid du Colombier 	int n = smbstrnput(s->buf, s->wn, s->maxlen, string, size, upcase);
1528ccd4a63SDavid du Colombier 	if (n <= 0)
1538ccd4a63SDavid du Colombier 		return 0;
1548ccd4a63SDavid du Colombier 	s->wn += n;
1558ccd4a63SDavid du Colombier 	return 1;
1568ccd4a63SDavid du Colombier }
1578ccd4a63SDavid du Colombier 
1588ccd4a63SDavid du Colombier ulong
smbbufferwriteoffset(SmbBuffer * s)1598ccd4a63SDavid du Colombier smbbufferwriteoffset(SmbBuffer *s)
1608ccd4a63SDavid du Colombier {
1618ccd4a63SDavid du Colombier 	return s->wn;
1628ccd4a63SDavid du Colombier }
1638ccd4a63SDavid du Colombier 
1648ccd4a63SDavid du Colombier ulong
smbbufferwritemaxoffset(SmbBuffer * s)1658ccd4a63SDavid du Colombier smbbufferwritemaxoffset(SmbBuffer *s)
1668ccd4a63SDavid du Colombier {
1678ccd4a63SDavid du Colombier 	return s->maxlen;
1688ccd4a63SDavid du Colombier }
1698ccd4a63SDavid du Colombier 
1708ccd4a63SDavid du Colombier ulong
smbbufferreadoffset(SmbBuffer * s)1718ccd4a63SDavid du Colombier smbbufferreadoffset(SmbBuffer *s)
1728ccd4a63SDavid du Colombier {
1738ccd4a63SDavid du Colombier 	return s->rn;
1748ccd4a63SDavid du Colombier }
1758ccd4a63SDavid du Colombier 
1768ccd4a63SDavid du Colombier void *
smbbufferreadpointer(SmbBuffer * s)1778ccd4a63SDavid du Colombier smbbufferreadpointer(SmbBuffer *s)
1788ccd4a63SDavid du Colombier {
1798ccd4a63SDavid du Colombier 	return s->buf + s->rn;
1808ccd4a63SDavid du Colombier }
1818ccd4a63SDavid du Colombier 
1828ccd4a63SDavid du Colombier void *
smbbufferwritepointer(SmbBuffer * s)1838ccd4a63SDavid du Colombier smbbufferwritepointer(SmbBuffer *s)
1848ccd4a63SDavid du Colombier {
1858ccd4a63SDavid du Colombier 	return s->buf + s->wn;
1868ccd4a63SDavid du Colombier }
1878ccd4a63SDavid du Colombier 
1888ccd4a63SDavid du Colombier ulong
smbbufferwritespace(SmbBuffer * b)1898ccd4a63SDavid du Colombier smbbufferwritespace(SmbBuffer *b)
1908ccd4a63SDavid du Colombier {
1918ccd4a63SDavid du Colombier 	return b->maxlen - b->wn;
1928ccd4a63SDavid du Colombier }
1938ccd4a63SDavid du Colombier 
1948ccd4a63SDavid du Colombier SmbBuffer *
smbbuffernew(ulong maxlen)1958ccd4a63SDavid du Colombier smbbuffernew(ulong maxlen)
1968ccd4a63SDavid du Colombier {
1978ccd4a63SDavid du Colombier 	SmbBuffer *b;
1988ccd4a63SDavid du Colombier 	b = smbemalloc(sizeof(SmbBuffer));
1998ccd4a63SDavid du Colombier 	b->buf = smbemalloc(maxlen);
2008ccd4a63SDavid du Colombier 	b->realmaxlen = b->maxlen = maxlen;
2018ccd4a63SDavid du Colombier 	b->rn = 0;
2028ccd4a63SDavid du Colombier 	b->wn = 0;
2038ccd4a63SDavid du Colombier 	b->flags = STRUCT | BUFFER;
2048ccd4a63SDavid du Colombier 	return b;
2058ccd4a63SDavid du Colombier }
2068ccd4a63SDavid du Colombier 
2078ccd4a63SDavid du Colombier void
smbbufferfree(SmbBuffer ** bp)2088ccd4a63SDavid du Colombier smbbufferfree(SmbBuffer **bp)
2098ccd4a63SDavid du Colombier {
2108ccd4a63SDavid du Colombier 	SmbBuffer *b = *bp;
2118ccd4a63SDavid du Colombier 	if (b) {
2128ccd4a63SDavid du Colombier 		if (b->flags & BUFFER) {
2138ccd4a63SDavid du Colombier 			free(b->buf);
2148ccd4a63SDavid du Colombier 			b->buf = nil;
2158ccd4a63SDavid du Colombier 			b->flags &= ~BUFFER;
2168ccd4a63SDavid du Colombier 		}
2178ccd4a63SDavid du Colombier 		if (b->flags & STRUCT)
2188ccd4a63SDavid du Colombier 			free(b);
2198ccd4a63SDavid du Colombier 		*bp = nil;
2208ccd4a63SDavid du Colombier 	}
2218ccd4a63SDavid du Colombier }
2228ccd4a63SDavid du Colombier 
2238ccd4a63SDavid du Colombier uchar *
smbbufferbase(SmbBuffer * b)2248ccd4a63SDavid du Colombier smbbufferbase(SmbBuffer *b)
2258ccd4a63SDavid du Colombier {
2268ccd4a63SDavid du Colombier 	return b->buf;
2278ccd4a63SDavid du Colombier }
2288ccd4a63SDavid du Colombier 
2298ccd4a63SDavid du Colombier int
smbbuffergetbytes(SmbBuffer * b,void * buf,ulong len)2308ccd4a63SDavid du Colombier smbbuffergetbytes(SmbBuffer *b, void *buf, ulong len)
2318ccd4a63SDavid du Colombier {
2328ccd4a63SDavid du Colombier 	if (b->rn + len > b->wn)
2338ccd4a63SDavid du Colombier 		return 0;
2348ccd4a63SDavid du Colombier 	if (buf)
2358ccd4a63SDavid du Colombier 		memcpy(buf, b->buf + b->rn, len);
2368ccd4a63SDavid du Colombier 	b->rn += len;
2378ccd4a63SDavid du Colombier 	return 1;
2388ccd4a63SDavid du Colombier }
2398ccd4a63SDavid du Colombier 
2408ccd4a63SDavid du Colombier void
smbbuffersetreadlen(SmbBuffer * b,ulong len)2418ccd4a63SDavid du Colombier smbbuffersetreadlen(SmbBuffer *b, ulong len)
2428ccd4a63SDavid du Colombier {
2438ccd4a63SDavid du Colombier 	b->wn = b->rn + len;
2448ccd4a63SDavid du Colombier }
2458ccd4a63SDavid du Colombier 
2468ccd4a63SDavid du Colombier int
smbbuffertrimreadlen(SmbBuffer * b,ulong len)2478ccd4a63SDavid du Colombier smbbuffertrimreadlen(SmbBuffer *b, ulong len)
2488ccd4a63SDavid du Colombier {
2498ccd4a63SDavid du Colombier 	if (b->rn + len > b->wn)
2508ccd4a63SDavid du Colombier 		return 0;
2518ccd4a63SDavid du Colombier 	else if (b->rn + len < b->wn)
2528ccd4a63SDavid du Colombier 		b->wn = b->rn + len;
2538ccd4a63SDavid du Colombier 	return 1;
2548ccd4a63SDavid du Colombier }
2558ccd4a63SDavid du Colombier 
2568ccd4a63SDavid du Colombier int
smbbuffergets(SmbBuffer * b,ushort * sp)2578ccd4a63SDavid du Colombier smbbuffergets(SmbBuffer *b, ushort *sp)
2588ccd4a63SDavid du Colombier {
2598ccd4a63SDavid du Colombier 	if (b->rn + 2 > b->wn)
2608ccd4a63SDavid du Colombier 		return 0;
2618ccd4a63SDavid du Colombier 	*sp = smbnhgets(b->buf + b->rn);
2628ccd4a63SDavid du Colombier 	b->rn += 2;
2638ccd4a63SDavid du Colombier 	return 1;
2648ccd4a63SDavid du Colombier }
2658ccd4a63SDavid du Colombier 
2668ccd4a63SDavid du Colombier int
smbbuffergetstrn(SmbBuffer * b,ushort size,char ** sp)2678ccd4a63SDavid du Colombier smbbuffergetstrn(SmbBuffer *b, ushort size, char **sp)
2688ccd4a63SDavid du Colombier {
2698ccd4a63SDavid du Colombier 	uchar *np;
2708ccd4a63SDavid du Colombier 	if (size > b->wn - b->rn)
2718ccd4a63SDavid du Colombier 		return 0;
2728ccd4a63SDavid du Colombier 	np = memchr(b->buf + b->rn, 0, size);
2738ccd4a63SDavid du Colombier 	if (np == nil)
2748ccd4a63SDavid du Colombier 		return 0;
2758ccd4a63SDavid du Colombier 	*sp = strdup((char *)b->buf + b->rn);
2768ccd4a63SDavid du Colombier 	b->rn += size;
2778ccd4a63SDavid du Colombier 	return 1;
2788ccd4a63SDavid du Colombier }
2798ccd4a63SDavid du Colombier 
2808ccd4a63SDavid du Colombier int
smbbuffergetstr(SmbBuffer * b,ulong flags,char ** sp)2818ccd4a63SDavid du Colombier smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp)
2828ccd4a63SDavid du Colombier {
283*b698dcfaSDavid du Colombier 	int c;
284*b698dcfaSDavid du Colombier 	char *p;
2858ccd4a63SDavid du Colombier 	uchar *np;
286*b698dcfaSDavid du Colombier 
2878ccd4a63SDavid du Colombier 	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
2888ccd4a63SDavid du Colombier 	if (np == nil)
2898ccd4a63SDavid du Colombier 		return 0;
2908ccd4a63SDavid du Colombier 	*sp = strdup((char *)b->buf + b->rn);
291*b698dcfaSDavid du Colombier 	for (p = *sp; *p != 0; p++) {
292*b698dcfaSDavid du Colombier 		c = *p;
293*b698dcfaSDavid du Colombier 		if (c >= 'a' && c <= 'z' && (flags & SMB_STRING_UPCASE))
294*b698dcfaSDavid du Colombier 			*p = toupper(c);
295*b698dcfaSDavid du Colombier 		else if (c == '/' && (flags & SMB_STRING_REVPATH))
296*b698dcfaSDavid du Colombier 			*p = '\\';
297*b698dcfaSDavid du Colombier 		else if (c == '\\' && (flags & SMB_STRING_PATH))
298*b698dcfaSDavid du Colombier 			*p = '/';
299*b698dcfaSDavid du Colombier 		else if (smbglobals.convertspace){
300*b698dcfaSDavid du Colombier 			if (c == 0xa0 && (flags & SMB_STRING_REVPATH))
301*b698dcfaSDavid du Colombier 				*p = ' ';
302*b698dcfaSDavid du Colombier 			else if (c == ' ' && (flags & SMB_STRING_PATH))
303*b698dcfaSDavid du Colombier 				*p = 0xa0;
304*b698dcfaSDavid du Colombier 		}
305*b698dcfaSDavid du Colombier 	}
3068ccd4a63SDavid du Colombier 	b->rn = np - b->buf + 1;
3078ccd4a63SDavid du Colombier 	return 1;
3088ccd4a63SDavid du Colombier }
3098ccd4a63SDavid du Colombier 
3108ccd4a63SDavid du Colombier int
smbbuffergetstrinline(SmbBuffer * b,char ** sp)3118ccd4a63SDavid du Colombier smbbuffergetstrinline(SmbBuffer *b, char **sp)
3128ccd4a63SDavid du Colombier {
3138ccd4a63SDavid du Colombier 	uchar *np;
3148ccd4a63SDavid du Colombier 	np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
3158ccd4a63SDavid du Colombier 	if (np == nil)
3168ccd4a63SDavid du Colombier 		return 0;
3178ccd4a63SDavid du Colombier 	*sp = (char *)b->buf + b->rn;
3188ccd4a63SDavid du Colombier 	b->rn = np - b->buf + 1;
3198ccd4a63SDavid du Colombier 	return 1;
3208ccd4a63SDavid du Colombier }
3218ccd4a63SDavid du Colombier 
3228ccd4a63SDavid du Colombier int
smbbuffergetucs2(SmbBuffer * b,ulong flags,char ** sp)3238ccd4a63SDavid du Colombier smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp)
3248ccd4a63SDavid du Colombier {
3258ccd4a63SDavid du Colombier 	uchar *bdata = b->buf + b->rn;
3268ccd4a63SDavid du Colombier 	uchar *edata = b->buf + b->wn;
3278ccd4a63SDavid du Colombier 	Rune r;
3288ccd4a63SDavid du Colombier 	int l;
3298ccd4a63SDavid du Colombier 	char *p, *q;
3308ccd4a63SDavid du Colombier 	uchar *savebdata;
3318ccd4a63SDavid du Colombier 	int first;
3328ccd4a63SDavid du Colombier 
3338ccd4a63SDavid du Colombier 	l = 0;
3348ccd4a63SDavid du Colombier 	if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1)
3358ccd4a63SDavid du Colombier 		bdata++;
3368ccd4a63SDavid du Colombier 	savebdata = bdata;
3378ccd4a63SDavid du Colombier 	first = 1;
3388ccd4a63SDavid du Colombier 	do {
3398ccd4a63SDavid du Colombier 		if (bdata + 2 > edata) {
3408ccd4a63SDavid du Colombier 			l++;
3418ccd4a63SDavid du Colombier 			break;
3428ccd4a63SDavid du Colombier 		}
3438ccd4a63SDavid du Colombier 		r = smbnhgets(bdata); bdata += 2;
3448ccd4a63SDavid du Colombier 		if (first && (flags & SMB_STRING_PATH) && r != '\\')
3458ccd4a63SDavid du Colombier 			l++;
3468ccd4a63SDavid du Colombier 		first = 0;
3478ccd4a63SDavid du Colombier 		if (flags & SMB_STRING_CONVERT_MASK)
3488ccd4a63SDavid du Colombier 			r = smbruneconvert(r, flags);
3498ccd4a63SDavid du Colombier 		l += runelen(r);
3508ccd4a63SDavid du Colombier 	} while (r != 0);
3518ccd4a63SDavid du Colombier 	p = smbemalloc(l);
3528ccd4a63SDavid du Colombier 	bdata = savebdata;
3538ccd4a63SDavid du Colombier 	q = p;
3548ccd4a63SDavid du Colombier 	first = 1;
3558ccd4a63SDavid du Colombier 	do {
3568ccd4a63SDavid du Colombier 		if (bdata + 2 > edata) {
3578ccd4a63SDavid du Colombier 			*q = 0;
3588ccd4a63SDavid du Colombier 			break;
3598ccd4a63SDavid du Colombier 		}
3608ccd4a63SDavid du Colombier 		r = smbnhgets(bdata); bdata += 2;
3618ccd4a63SDavid du Colombier 		if (first && (flags & SMB_STRING_PATH) && r != '\\')
3628ccd4a63SDavid du Colombier 			*q++ = '/';
3638ccd4a63SDavid du Colombier 		first = 0;
3648ccd4a63SDavid du Colombier 		if (flags & SMB_STRING_CONVERT_MASK)
3658ccd4a63SDavid du Colombier 			r = smbruneconvert(r, flags);
3668ccd4a63SDavid du Colombier 		q += runetochar(q, &r);
3678ccd4a63SDavid du Colombier 	} while (r != 0);
3688ccd4a63SDavid du Colombier 	b->rn = bdata - b->buf;
3698ccd4a63SDavid du Colombier 	*sp = p;
3708ccd4a63SDavid du Colombier 	return 1;
3718ccd4a63SDavid du Colombier }
3728ccd4a63SDavid du Colombier 
3738ccd4a63SDavid du Colombier int
smbbuffergetstring(SmbBuffer * b,SmbHeader * h,ulong flags,char ** sp)3748ccd4a63SDavid du Colombier smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp)
3758ccd4a63SDavid du Colombier {
3768ccd4a63SDavid du Colombier 	if (flags & SMB_STRING_UNICODE)
3778ccd4a63SDavid du Colombier 		return smbbuffergetucs2(b, flags, sp);
3788ccd4a63SDavid du Colombier 	else if (flags & SMB_STRING_ASCII)
3798ccd4a63SDavid du Colombier 		return smbbuffergetstr(b, flags, sp);
3808ccd4a63SDavid du Colombier 	else if (h->flags2 & SMB_FLAGS2_UNICODE)
3818ccd4a63SDavid du Colombier 		return smbbuffergetucs2(b, flags, sp);
3828ccd4a63SDavid du Colombier 	else
3838ccd4a63SDavid du Colombier 		return smbbuffergetstr(b, flags, sp);
3848ccd4a63SDavid du Colombier }
3858ccd4a63SDavid du Colombier 
3868ccd4a63SDavid du Colombier void *
smbbufferpointer(SmbBuffer * b,ulong offset)3878ccd4a63SDavid du Colombier smbbufferpointer(SmbBuffer *b, ulong offset)
3888ccd4a63SDavid du Colombier {
3898ccd4a63SDavid du Colombier 	return b->buf + offset;
3908ccd4a63SDavid du Colombier }
3918ccd4a63SDavid du Colombier 
3928ccd4a63SDavid du Colombier int
smbbuffergetb(SmbBuffer * b,uchar * bp)3938ccd4a63SDavid du Colombier smbbuffergetb(SmbBuffer *b, uchar *bp)
3948ccd4a63SDavid du Colombier {
3958ccd4a63SDavid du Colombier 	if (b->rn < b->wn) {
3968ccd4a63SDavid du Colombier 		*bp = b->buf[b->rn++];
3978ccd4a63SDavid du Colombier 		return 1;
3988ccd4a63SDavid du Colombier 	}
3998ccd4a63SDavid du Colombier 	return 0;
4008ccd4a63SDavid du Colombier }
4018ccd4a63SDavid du Colombier 
4028ccd4a63SDavid du Colombier int
smbbuffergetl(SmbBuffer * b,ulong * lp)4038ccd4a63SDavid du Colombier smbbuffergetl(SmbBuffer *b, ulong *lp)
4048ccd4a63SDavid du Colombier {
4058ccd4a63SDavid du Colombier 	if (b->rn + 4 <= b->wn) {
4068ccd4a63SDavid du Colombier 		*lp = smbnhgetl(b->buf + b->rn);
4078ccd4a63SDavid du Colombier 		b->rn += 4;
4088ccd4a63SDavid du Colombier 		return 1;
4098ccd4a63SDavid du Colombier 	}
4108ccd4a63SDavid du Colombier 	return 0;
4118ccd4a63SDavid du Colombier }
4128ccd4a63SDavid du Colombier 
4138ccd4a63SDavid du Colombier int
smbbuffergetv(SmbBuffer * b,vlong * vp)4148ccd4a63SDavid du Colombier smbbuffergetv(SmbBuffer *b, vlong *vp)
4158ccd4a63SDavid du Colombier {
4168ccd4a63SDavid du Colombier 	if (b->rn + 8 <= b->wn) {
4178ccd4a63SDavid du Colombier 		*vp = smbnhgetv(b->buf + b->rn);
4188ccd4a63SDavid du Colombier 		b->rn += 8;
4198ccd4a63SDavid du Colombier 		return 1;
4208ccd4a63SDavid du Colombier 	}
421ec46fab0SDavid du Colombier 	return 0;
4228ccd4a63SDavid du Colombier }
4238ccd4a63SDavid du Colombier 
4248ccd4a63SDavid du Colombier ulong
smbbufferreadspace(SmbBuffer * b)4258ccd4a63SDavid du Colombier smbbufferreadspace(SmbBuffer *b)
4268ccd4a63SDavid du Colombier {
4278ccd4a63SDavid du Colombier 	return b->wn - b->rn;
4288ccd4a63SDavid du Colombier }
4298ccd4a63SDavid du Colombier 
4308ccd4a63SDavid du Colombier void
smbbufferwritelimit(SmbBuffer * b,ulong limit)4318ccd4a63SDavid du Colombier smbbufferwritelimit(SmbBuffer *b, ulong limit)
4328ccd4a63SDavid du Colombier {
4338ccd4a63SDavid du Colombier 	if (b->rn + limit < b->maxlen)
4348ccd4a63SDavid du Colombier 		b->maxlen = b->rn + limit;
4358ccd4a63SDavid du Colombier }
4368ccd4a63SDavid du Colombier 
4378ccd4a63SDavid du Colombier int
smbbufferreadskipto(SmbBuffer * b,ulong offset)4388ccd4a63SDavid du Colombier smbbufferreadskipto(SmbBuffer *b, ulong offset)
4398ccd4a63SDavid du Colombier {
4408ccd4a63SDavid du Colombier 	if (offset < b->rn || offset >= b->wn)
4418ccd4a63SDavid du Colombier 		return 0;
4428ccd4a63SDavid du Colombier 	b->rn = offset;
4438ccd4a63SDavid du Colombier 	return 1;
4448ccd4a63SDavid du Colombier }
4458ccd4a63SDavid du Colombier 
4468ccd4a63SDavid du Colombier int
smbbufferpushreadlimit(SmbBuffer * b,ulong limit)4478ccd4a63SDavid du Colombier smbbufferpushreadlimit(SmbBuffer *b, ulong limit)
4488ccd4a63SDavid du Colombier {
4498ccd4a63SDavid du Colombier 	if (b->flags & PUSHED)
4508ccd4a63SDavid du Colombier 		return 0;
4518ccd4a63SDavid du Colombier 	if (limit > b->wn || limit < b->rn)
4528ccd4a63SDavid du Colombier 		return 0;
4538ccd4a63SDavid du Colombier 	b->savewn = b->wn;
4548ccd4a63SDavid du Colombier 	b->wn = limit;
4558ccd4a63SDavid du Colombier 	b->flags |= PUSHED;
4568ccd4a63SDavid du Colombier 	return 1;
4578ccd4a63SDavid du Colombier }
4588ccd4a63SDavid du Colombier 
4598ccd4a63SDavid du Colombier int
smbbufferpopreadlimit(SmbBuffer * b)4608ccd4a63SDavid du Colombier smbbufferpopreadlimit(SmbBuffer *b)
4618ccd4a63SDavid du Colombier {
4628ccd4a63SDavid du Colombier 	if ((b->flags & PUSHED) == 0)
4638ccd4a63SDavid du Colombier 		return 0;
4648ccd4a63SDavid du Colombier 	b->wn = b->savewn;
4658ccd4a63SDavid du Colombier 	b->flags &= ~PUSHED;
4668ccd4a63SDavid du Colombier 	return 1;
4678ccd4a63SDavid du Colombier }
4688ccd4a63SDavid du Colombier 
4698ccd4a63SDavid du Colombier int
smbbufferwritebackup(SmbBuffer * b,ulong offset)4708ccd4a63SDavid du Colombier smbbufferwritebackup(SmbBuffer *b, ulong offset)
4718ccd4a63SDavid du Colombier {
4728ccd4a63SDavid du Colombier 	if (offset >= b->rn && offset <= b->wn) {
4738ccd4a63SDavid du Colombier 		b->wn = offset;
4748ccd4a63SDavid du Colombier 		return 1;
4758ccd4a63SDavid du Colombier 	}
4768ccd4a63SDavid du Colombier 	return 0;
4778ccd4a63SDavid du Colombier }
4788ccd4a63SDavid du Colombier 
4798ccd4a63SDavid du Colombier int
smbbufferreadbackup(SmbBuffer * b,ulong offset)4808ccd4a63SDavid du Colombier smbbufferreadbackup(SmbBuffer *b, ulong offset)
4818ccd4a63SDavid du Colombier {
4828ccd4a63SDavid du Colombier 	if (offset <= b->rn) {
4838ccd4a63SDavid du Colombier 		b->rn = offset;
4848ccd4a63SDavid du Colombier 		return 1;
4858ccd4a63SDavid du Colombier 	}
4868ccd4a63SDavid du Colombier 	return 0;
4878ccd4a63SDavid du Colombier }
4888ccd4a63SDavid du Colombier 
4898ccd4a63SDavid du Colombier int
smbbufferfixuprelatives(SmbBuffer * b,ulong fixupoffset)4908ccd4a63SDavid du Colombier smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset)
4918ccd4a63SDavid du Colombier {
4928ccd4a63SDavid du Colombier 	ulong fixval;
4938ccd4a63SDavid du Colombier 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
4948ccd4a63SDavid du Colombier 		return 0;
4958ccd4a63SDavid du Colombier 	fixval = b->wn - fixupoffset - 2;
4968ccd4a63SDavid du Colombier 	if (fixval > 65535)
4978ccd4a63SDavid du Colombier 		return 0;
4988ccd4a63SDavid du Colombier 	smbhnputs(b->buf + fixupoffset, fixval);
4998ccd4a63SDavid du Colombier 	return 1;
5008ccd4a63SDavid du Colombier }
5018ccd4a63SDavid du Colombier 
5028ccd4a63SDavid du Colombier int
smbbufferfixuprelativel(SmbBuffer * b,ulong fixupoffset)5038ccd4a63SDavid du Colombier smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset)
5048ccd4a63SDavid du Colombier {
5058ccd4a63SDavid du Colombier 	ulong fixval;
5068ccd4a63SDavid du Colombier 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
5078ccd4a63SDavid du Colombier 		return 0;
5088ccd4a63SDavid du Colombier 	fixval = b->wn - fixupoffset - 4;
5098ccd4a63SDavid du Colombier 	smbhnputl(b->buf + fixupoffset, fixval);
5108ccd4a63SDavid du Colombier 	return 1;
5118ccd4a63SDavid du Colombier }
5128ccd4a63SDavid du Colombier 
5138ccd4a63SDavid du Colombier int
smbbufferfixupabsolutes(SmbBuffer * b,ulong fixupoffset)5148ccd4a63SDavid du Colombier smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset)
5158ccd4a63SDavid du Colombier {
5168ccd4a63SDavid du Colombier 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
5178ccd4a63SDavid du Colombier 		return 0;
5188ccd4a63SDavid du Colombier 	if (b->wn > 65535)
5198ccd4a63SDavid du Colombier 		return 0;
5208ccd4a63SDavid du Colombier 	smbhnputs(b->buf + fixupoffset, b->wn);
5218ccd4a63SDavid du Colombier 	return 1;
5228ccd4a63SDavid du Colombier }
5238ccd4a63SDavid du Colombier 
5248ccd4a63SDavid du Colombier int
smbbufferfixupl(SmbBuffer * b,ulong fixupoffset,ulong fixupval)5258ccd4a63SDavid du Colombier smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong fixupval)
5268ccd4a63SDavid du Colombier {
5278ccd4a63SDavid du Colombier 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
5288ccd4a63SDavid du Colombier 		return 0;
5298ccd4a63SDavid du Colombier 	smbhnputl(b->buf + fixupoffset, fixupval);
5308ccd4a63SDavid du Colombier 	return 1;
5318ccd4a63SDavid du Colombier }
5328ccd4a63SDavid du Colombier 
5338ccd4a63SDavid du Colombier int
smbbufferfixupabsolutel(SmbBuffer * b,ulong fixupoffset)5348ccd4a63SDavid du Colombier smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset)
5358ccd4a63SDavid du Colombier {
5368ccd4a63SDavid du Colombier 	if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
5378ccd4a63SDavid du Colombier 		return 0;
5388ccd4a63SDavid du Colombier 	smbhnputl(b->buf + fixupoffset, b->wn);
5398ccd4a63SDavid du Colombier 	return 1;
5408ccd4a63SDavid du Colombier }
5418ccd4a63SDavid du Colombier 
5428ccd4a63SDavid du Colombier int
smbbufferfixuprelativeinclusivel(SmbBuffer * b,ulong fixupoffset)5438ccd4a63SDavid du Colombier smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset)
5448ccd4a63SDavid du Colombier {
5458ccd4a63SDavid du Colombier 	if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
5468ccd4a63SDavid du Colombier 		return 0;
5478ccd4a63SDavid du Colombier 	smbhnputl(b->buf + fixupoffset, b->wn - fixupoffset);
5488ccd4a63SDavid du Colombier 	return 1;
5498ccd4a63SDavid du Colombier }
5508ccd4a63SDavid du Colombier 
5518ccd4a63SDavid du Colombier int
smbbufferfill(SmbBuffer * b,uchar val,ulong len)5528ccd4a63SDavid du Colombier smbbufferfill(SmbBuffer *b, uchar val, ulong len)
5538ccd4a63SDavid du Colombier {
5548ccd4a63SDavid du Colombier 	if (b->maxlen - b->wn < len)
5558ccd4a63SDavid du Colombier 		return 0;
5568ccd4a63SDavid du Colombier 	memset(b->buf + b->wn, val, len);
5578ccd4a63SDavid du Colombier 	b->wn += len;
5588ccd4a63SDavid du Colombier 	return 1;
5598ccd4a63SDavid du Colombier }
5608ccd4a63SDavid du Colombier 
5618ccd4a63SDavid du Colombier int
smbbufferoffsetgetb(SmbBuffer * b,ulong offset,uchar * bp)5628ccd4a63SDavid du Colombier smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp)
5638ccd4a63SDavid du Colombier {
5648ccd4a63SDavid du Colombier 	if (offset >= b->rn && offset + 1 <= b->wn) {
5658ccd4a63SDavid du Colombier 		*bp = b->buf[b->rn + offset];
5668ccd4a63SDavid du Colombier 		return 1;
5678ccd4a63SDavid du Colombier 	}
5688ccd4a63SDavid du Colombier 	return 0;
5698ccd4a63SDavid du Colombier }
5708ccd4a63SDavid du Colombier 
5718ccd4a63SDavid du Colombier int
smbbuffercopy(SmbBuffer * to,SmbBuffer * from,ulong amount)5728ccd4a63SDavid du Colombier smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount)
5738ccd4a63SDavid du Colombier {
5748ccd4a63SDavid du Colombier 	if (smbbufferreadspace(from) < amount)
5758ccd4a63SDavid du Colombier 		return 0;
5768ccd4a63SDavid du Colombier 	if (smbbufferputbytes(to, smbbufferreadpointer(from), amount)) {
5778ccd4a63SDavid du Colombier 		assert(smbbuffergetbytes(from, nil, amount));
5788ccd4a63SDavid du Colombier 		return 1;
5798ccd4a63SDavid du Colombier 	}
5808ccd4a63SDavid du Colombier 	return 0;
5818ccd4a63SDavid du Colombier }
5828ccd4a63SDavid du Colombier 
5838ccd4a63SDavid du Colombier int
smbbufferoffsetcopystr(SmbBuffer * b,ulong offset,char * buf,int buflen,int * lenp)5848ccd4a63SDavid du Colombier smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp)
5858ccd4a63SDavid du Colombier {
5868ccd4a63SDavid du Colombier 	uchar *np;
5878ccd4a63SDavid du Colombier 	if (offset < b->rn || offset >= b->wn)
5888ccd4a63SDavid du Colombier 		return 0;
5898ccd4a63SDavid du Colombier 	np = memchr(b->buf + offset, 0, b->wn - offset);
5908ccd4a63SDavid du Colombier 	if (np == nil)
5918ccd4a63SDavid du Colombier 		return 0;
5928ccd4a63SDavid du Colombier 	*lenp = np - (b->buf + offset) + 1;
5938ccd4a63SDavid du Colombier 	if (*lenp > buflen)
5948ccd4a63SDavid du Colombier 		return 0;
5958ccd4a63SDavid du Colombier 	memcpy(buf, b->buf + offset, *lenp);
5968ccd4a63SDavid du Colombier 	return 1;
5978ccd4a63SDavid du Colombier }
598