]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cifs/pack.c
upas/fs: remove useless loop in rf822()
[plan9front.git] / sys / src / cmd / cifs / pack.c
1 /* packet packing and unpacking */
2 #include <u.h>
3 #include <libc.h>
4 #include <ctype.h>
5 #include "cifs.h"
6
7 void *
8 pmem(Pkt *p, void *v, int len)
9 {
10         uchar *str = v;
11         void *s = p->pos;
12
13         if(!len || !v)
14                 return s;
15         while(len--)
16                 *p->pos++ = *str++;
17         return s;
18 }
19
20 void *
21 ppath(Pkt *p, char *str)
22 {
23         char c;
24         Rune r;
25         void *s = p->pos;
26
27         if(!str)
28                 return s;
29
30         if(p->s->flags2 & FL2_UNICODE){
31                 if(((p->pos - p->buf) % 2) != 0)        /* pad to even offset */
32                         p8(p, 0);
33                 while(*str){
34                         str += chartorune(&r, str);
35                         if(r > Bits16)
36                                 sysfatal("ppath: %C/%x utf too wide for windows\n", r, r);
37                         if(r == L'/')
38                                 r = L'\\';
39                         pl16(p, r);
40                 }
41                 pl16(p, 0);
42         } else {
43                 while((c = *str++) != 0){
44                         if(c == '/')
45                                 c = '\\';
46                         *p->pos++ = c;
47                 }
48                 *p->pos++ = 0;
49         }
50         return s;
51 }
52
53 void *
54 pstr(Pkt *p, char *str)
55 {
56         void *s = p->pos;
57         Rune r;
58
59         if(!str)
60                 return s;
61
62         if(p->s->flags2 & FL2_UNICODE){
63                 if(((p->pos - p->buf) % 2) != 0)
64                         p8(p, 0);               /* pad to even offset */
65                 while(*str){
66                         str += chartorune(&r, str);
67                         if(r > Bits16)
68                                 sysfatal("pstr: %C/%x utf too wide for windows\n", r, r);
69                         pl16(p, r);
70                 }
71                 pl16(p, 0);
72         } else {
73                 while(*str)
74                         *p->pos++ = *str++;
75                 *p->pos++ = 0;
76         }
77         return s;
78 }
79
80 void *
81 pascii(Pkt *p, char *str)
82 {
83         void *s = p->pos;
84
85         while(*str)
86                 *p->pos++ = *str++;
87         *p->pos++ = 0;
88         return s;
89 }
90
91
92 void *
93 pl64(Pkt *p, uvlong n)
94 {
95         void *s = p->pos;
96
97         *p->pos++ = n;
98         *p->pos++ = n >> 8;
99         *p->pos++ = n >> 16;
100         *p->pos++ = n >> 24;
101         *p->pos++ = n >> 32;
102         *p->pos++ = n >> 40;
103         *p->pos++ = n >> 48;
104         *p->pos++ = n >> 56;
105         return s;
106 }
107
108 void *
109 pb32(Pkt *p, uint n)
110 {
111         void *s = p->pos;
112
113         *p->pos++ = n >> 24;
114         *p->pos++ = n >> 16;
115         *p->pos++ = n >> 8;
116         *p->pos++ = n;
117         return s;
118 }
119
120 void *
121 pl32(Pkt *p, uint n)
122 {
123         void *s = p->pos;
124
125         *p->pos++ = n;
126         *p->pos++ = n >> 8;
127         *p->pos++ = n >> 16;
128         *p->pos++ = n >> 24;
129         return s;
130 }
131
132 void *
133 pb16(Pkt *p, uint n)
134 {
135         void *s = p->pos;
136
137         *p->pos++ = n >> 8;
138         *p->pos++ = n;
139         return s;
140 }
141
142 void *
143 pl16(Pkt *p, uint n)
144 {
145         void *s = p->pos;
146
147         *p->pos++ = n;
148         *p->pos++ = n >> 8;
149         return s;
150 }
151
152 void *
153 p8(Pkt *p, uint n)
154 {
155         void *s = p->pos;
156
157         *p->pos++ = n;
158         return s;
159 }
160
161 /*
162  * Encode a Netbios name
163  */
164 void *
165 pname(Pkt *p, char *name, char pad)
166 {
167         int i, done = 0;
168         char c;
169         void *s = p->pos;
170
171         *p->pos++ = ' ';
172         for(i = 0; i < 16; i++) {
173                 c = pad;
174                 if(!done && name[i] == '\0')
175                         done = 1;
176                 if(!done)
177                         c = islower(name[i])? toupper(name[i]): name[i];
178                 *p->pos++ = ((uchar)c >> 4) + 'A';
179                 *p->pos++ = (c & 0xf) + 'A';
180         }
181         *p->pos++ = '\0';
182         return s;
183 }
184
185 void *
186 pvtime(Pkt *p, uvlong n)
187 {
188         void *s = p->pos;
189
190         n += 11644473600LL;
191         n *= 10000000LL;
192
193         pl32(p, n);
194         pl32(p, n >> 32);
195         return s;
196 }
197
198 void *
199 pdatetime(Pkt *p, long utc)
200 {
201         void *s = p->pos;
202         Tm *tm = localtime(utc);
203         int t = tm->hour << 11 | tm->min << 5 | (tm->sec / 2);
204         int d = (tm->year - 80) << 9 | (tm->mon + 1) << 5 | tm->mday;
205
206         /*
207          * bug in word swapping in Win95 requires this
208          */
209         if(p->s->caps & CAP_NT_SMBS){
210                 pl16(p, d);
211                 pl16(p, t);
212         } else{
213                 pl16(p, t);
214                 pl16(p, d);
215         }
216         return s;
217 }
218
219
220 void
221 gmem(Pkt *p, void *v, int n)
222 {
223         uchar *str = v;
224
225         if(!n || !v)
226                 return;
227         while(n-- && p->pos < p->eop)
228                 *str++ = *p->pos++;
229 }
230
231 /*
232  * note len is the length of the source string in
233  * in runes or bytes, in ASCII mode this is also the size
234  * of the output buffer but this is not so in Unicode mode!
235  */
236 static void
237 _gstr(Pkt *p, char *str, int n, int align)
238 {
239         int i;
240         Rune r;
241
242         if(!n || !str)
243                 return;
244
245         if(p->flags2 & FL2_UNICODE){
246                 if(((p->pos - p->buf) % 2) != 0){
247                         if(align)
248                                 abort();
249                 }
250                 i = 0;
251                 while(*p->pos && n && p->pos < p->eop){
252                         r = gl16(p);
253                         i += runetochar(str +i, &r);
254                         n -= 2;
255                 }
256                 *(str + i) = 0;
257                 while(*p->pos && p->pos < p->eop)
258                         gl16(p);
259                 /*
260                  * some versions of windows terminate a rune string
261                  * with a single nul so we do a dangerous hack...
262                  */
263                 if(p->pos[1])
264                         g8(p);
265                 else
266                         gl16(p);
267         } else {
268                 while(*p->pos && n-- && p->pos < p->eop)
269                         *str++ = *p->pos++;
270                 *str = 0;
271                 while(*p->pos++ && p->pos < p->eop)
272                         continue;
273         }
274 }
275
276 void
277 gstr(Pkt *p, char *str, int n)
278 {
279         _gstr(p, str, n, 1);
280 }
281
282 void
283 gstr_noalign(Pkt *p, char *str, int n)
284 {
285         _gstr(p, str, n, 0);
286 }
287
288 /*
289  * Because DFS uses a string heap rather than strings embedded in the
290  * data packet, experience (rather than any spec) tells, us we must
291  * turn off the 16bit alignment for unicode strings.
292  */
293 void
294 goff(Pkt *p, uchar *base, char *str, int n)
295 {
296         int off;
297         uchar *pos;
298
299         off = gl16(p);
300         if(off == 0 || base + off > p->eop){
301                 memset(str, 0, n);
302                 return;
303         }
304         pos = p->pos;
305         p->pos = base + off;
306         gstr_noalign(p, str, n);
307         p->pos = pos;
308 }
309
310 void
311 gascii(Pkt *p, char *str, int n)
312 {
313         if(!n || !str)
314                 return;
315
316         while(*p->pos && n-- && p->pos < p->eop)
317                 *str++ = *p->pos++;
318         *str = 0;
319         while(*p->pos++ && p->pos < p->eop)
320                 continue;
321 }
322
323
324 uvlong
325 gl64(Pkt *p)
326 {
327         uvlong n;
328
329         if(p->pos + 8 > p->eop)
330                 return 0;
331
332         n  = (uvlong)*p->pos++;
333         n |= (uvlong)*p->pos++ << 8;
334         n |= (uvlong)*p->pos++ << 16;
335         n |= (uvlong)*p->pos++ << 24;
336         n |= (uvlong)*p->pos++ << 32;
337         n |= (uvlong)*p->pos++ << 40;
338         n |= (uvlong)*p->pos++ << 48;
339         n |= (uvlong)*p->pos++ << 56;
340         return n;
341 }
342
343 uvlong
344 gb48(Pkt *p)
345 {
346         uvlong n;
347
348         if(p->pos + 6 > p->eop)
349                 return 0;
350
351         n  = (uvlong)*p->pos++ << 40;
352         n |= (uvlong)*p->pos++ << 24;
353         n |= (uvlong)*p->pos++ << 32;
354         n |= (uvlong)*p->pos++ << 16;
355         n |= (uvlong)*p->pos++ << 8;
356         n |= (uvlong)*p->pos++;
357         return n;
358 }
359
360 uint
361 gb32(Pkt *p)
362 {
363         uint n;
364
365         if(p->pos + 4 > p->eop)
366                 return 0;
367
368         n  = (uint)*p->pos++ << 24;
369         n |= (uint)*p->pos++ << 16;
370         n |= (uint)*p->pos++ << 8;
371         n |= (uint)*p->pos++;
372         return n;
373 }
374
375 uint
376 gl32(Pkt *p)
377 {
378         uint n;
379
380         if(p->pos + 4 > p->eop)
381                 return 0;
382
383         n  = (uint)*p->pos++;
384         n |= (uint)*p->pos++ << 8;
385         n |= (uint)*p->pos++ << 16;
386         n |= (uint)*p->pos++ << 24;
387         return n;
388 }
389
390 uint
391 gb16(Pkt *p)
392 {
393         uint n;
394
395         if(p->pos + 2 > p->eop)
396                 return 0;
397         n  = (uint)*p->pos++ << 8;
398         n |= (uint)*p->pos++;
399         return n;
400 }
401
402 uint
403 gl16(Pkt *p)
404 {
405         uint n;
406
407         if(p->pos + 2 > p->eop)
408                 return 0;
409         n  = (uint)*p->pos++;
410         n |= (uint)*p->pos++ << 8;
411         return n;
412 }
413
414 uint
415 g8(Pkt *p)
416 {
417         if(p->pos + 1 > p->eop)
418                 return 0;
419         return (uint)*p->pos++;
420 }
421
422 long
423 gdatetime(Pkt *p)
424 {
425         Tm tm;
426         uint d, t;
427
428         if(p->pos + 4 > p->eop)
429                 return 0;
430
431         /*
432          * bug in word swapping in Win95 requires this
433          */
434         if(p->s->caps & CAP_NT_SMBS){
435                 d = gl16(p);
436                 t = gl16(p);
437         }else{
438                 t = gl16(p);
439                 d = gl16(p);
440         }
441
442         tm.year = 80 + (d >> 9);
443         tm.mon = ((d >> 5) & 017) - 1;
444         tm.mday = d & 037;
445         tm.zone[0] = 0;
446         tm.tzoff = p->s->tz;
447
448         tm.hour = t >> 11;
449         tm.min = (t >> 5) & 63;
450         tm.sec = (t & 31) << 1;
451
452         return tm2sec(&tm);
453 }
454
455 long
456 gvtime(Pkt *p)
457 {
458         uvlong vl;
459
460         if(p->pos + 8 > p->eop)
461                 return 0;
462
463         vl  = (uvlong)gl32(p);
464         vl |= (uvlong)gl32(p) << 32;
465
466         vl /= 10000000LL;
467         vl -= 11644473600LL;
468         return vl;
469 }
470
471 void
472 gconv(Pkt *p, int conv, char *str, int n)
473 {
474         int off;
475         uchar *pos;
476
477         off = gl32(p) & 0xffff;
478         if(off == 0 || p->tdata - conv + off > p->eop){
479                 memset(str, 0, n);
480                 return;
481         }
482
483         pos = p->pos;
484         p->pos = p->tdata - conv + off;
485         gascii(p, str, n);
486         p->pos = pos;
487 }
488