1 #include "headers.h"
2
3 static void
smblogprintattr(int cmd,ushort attr)4 smblogprintattr(int cmd, ushort attr)
5 {
6 if (attr & SMB_ATTR_READ_ONLY)
7 smblogprint(cmd, " readonly");
8 if (attr & SMB_ATTR_HIDDEN)
9 smblogprint(cmd, " hidden");
10 if (attr & SMB_ATTR_SYSTEM)
11 smblogprint(cmd, " system");
12 if (attr & SMB_ATTR_DIRECTORY)
13 smblogprint(cmd, " directory");
14 if (attr & SMB_ATTR_ARCHIVE)
15 smblogprint(cmd, " archive");
16 }
17
18 static SmbFile *
openfile(SmbSession * s,SmbTree * t,char * path,ushort mode,ushort attr,ushort ofun,ulong createoptions,uvlong createsize,ushort * fidp,Dir ** dp,ushort * actionp)19 openfile(SmbSession *s, SmbTree *t, char *path, ushort mode, ushort attr, ushort ofun, ulong createoptions, uvlong createsize,
20 ushort *fidp, Dir **dp, ushort *actionp)
21 {
22 int p9mode;
23 int share;
24 Dir *d = nil;
25 int fd = -1;
26 ushort action;
27 SmbFile *f = nil;
28 SmbSharedFile *sf = nil;
29 char *fullpath = nil;
30 int diropen = 0;
31
32 //smblogprint(-1, "%s A %r", path);
33 p9mode = (mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK;
34 share = (mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK;
35 if (share == SMB_OPEN_MODE_SHARE_COMPATIBILITY) {
36 badshare:
37 //smblogprint(-1, "%s SMB_OPEN_MODE_SHARE_COMPATIBILITY", path);
38 smbseterror(s, ERRDOS, ERRbadshare);
39 goto done;
40 }
41 smbstringprint(&fullpath, "%s%s", t->serv->path, path);
42 d = dirstat(fullpath);
43 if (d) {
44 /* file exists */
45 int ofunexist;
46 if (d->mode & DMDIR) {
47 if (createoptions & SMB_CO_FILE) {
48 smbseterror(s, ERRDOS, ERRnoaccess);
49 goto done;
50 }
51 }
52 else if (createoptions & SMB_CO_DIRECTORY) {
53 smbseterror(s, ERRDOS, ERRnoaccess);
54 goto done;
55 }
56
57 sf = smbsharedfileget(d, p9mode, &share);
58 if (sf == nil)
59 goto badshare;
60 action = 1;
61 ofunexist = (ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK;
62 if (ofunexist == SMB_OFUN_EXIST_FAIL) {
63 smbseterror(s, ERRDOS, ERRfilexists);
64 goto done;
65 }
66 else if (ofunexist == SMB_OFUN_EXIST_TRUNCATE) {
67 if ((d->mode & DMDIR) || (p9mode != OWRITE && p9mode != ORDWR)) {
68 smbseterror(s, ERRDOS, ERRbadaccess);
69 goto done;
70 }
71 p9mode |= OTRUNC;
72 action = 3;
73 }
74 else if (ofunexist != SMB_OFUN_EXIST_OPEN) {
75 smbseterror(s, ERRDOS, ERRbadaccess);
76 goto done;
77 }
78 if (d->mode & DMDIR)
79 diropen = 1;
80 else
81 fd = open(fullpath, p9mode);
82 }
83 else {
84 /* file does not exist */
85 ulong p9attr;
86 action = 3;
87 if ((ofun & SMB_OFUN_NOEXIST_CREATE) == 0) {
88 smbseterror(s, ERRDOS, ERRbadfile);
89 goto done;
90 }
91 if (createsize != 0) {
92 smbseterror(s, ERRDOS, ERRunsup);
93 goto done;
94 }
95 //smblogprint(-1, "creating: attr 0x%.4ux co 0x%.8lux\n", attr, createoptions);
96 if (createoptions & SMB_CO_FILE) {
97 attr &= SMB_ATTR_DIRECTORY;
98 if (attr == 0)
99 attr = SMB_ATTR_NORMAL;
100 }
101 else if (createoptions & SMB_CO_DIRECTORY) {
102 attr &= ~SMB_ATTR_NORMAL;
103 attr |= SMB_ATTR_DIRECTORY;
104 p9mode = OREAD;
105 }
106 //smblogprint(-1, "creating: before conversion attr 0x%.4ux\n", attr);
107 p9attr = smbdosattr2plan9mode(attr);
108 //smblogprint(-1, "creating: after conversion p9attr 0%.uo\n", p9attr);
109 fd = create(fullpath, p9mode, p9attr);
110 if (fd >= 0) {
111 d = dirfstat(fd);
112 sf = smbsharedfileget(d, p9mode, &share);
113 if (sf == nil) {
114 close(fd);
115 remove(path);
116 goto badshare;
117 }
118 }
119 }
120 //smblogprint(-1, "%s D %r", fullpath);
121 if (!diropen && fd < 0) {
122 smbseterror(s, ERRSRV, ERRaccess);
123 goto done;
124 }
125 f = smbemalloc(sizeof(SmbFile));
126 if (diropen) {
127 f->ioallowed = 0;
128 f->fd = -1;
129 }
130 else {
131 f->ioallowed = 1;
132 f->fd = fd;
133 }
134 f->name = smbestrdup(path);
135 f->sf = sf;
136 sf = nil;
137 f->share = share;
138 f->p9mode = p9mode;
139 f->t = t;
140 if (s->fidmap == nil)
141 s->fidmap = smbidmapnew();
142 *fidp = smbidmapadd(s->fidmap, f);
143 //smblogprint(h->command, "REPLY:\n t->id=0x%ux fid=%d path=%s\n", t->id, *fidp, path);
144 smblogprintif(smbglobals.log.fids, "openfile: 0x%.4ux/0x%.4ux %s\n", t->id, *fidp, path);
145 if (actionp)
146 *actionp = action;
147 if (dp) {
148 *dp = d;
149 d = nil;
150 }
151 done:
152 if (sf)
153 smbsharedfileput(nil, sf, share);
154 free(d);
155 free(fullpath);
156 return f;
157 }
158
159 SmbProcessResult
smbcomopenandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)160 smbcomopenandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
161 {
162 uchar andxcommand;
163 ushort andxoffset, flags, mode, sattr, attr;
164 ulong createtime;
165 ushort ofun;
166 ulong createsize, timeout;
167 char *path = nil;
168 ulong andxoffsetfixupoffset;
169 SmbProcessResult pr;
170 ushort action;
171 Dir *d = nil;
172 SmbFile *f;
173 SmbTree *t;
174 ushort fid;
175
176 if (!smbcheckwordcount("comopenandx", h, 15))
177 return SmbProcessResultFormat;
178
179 andxcommand = *pdata++;
180 pdata++;
181 andxoffset = smbnhgets(pdata); pdata += 2;
182 flags = smbnhgets(pdata); pdata += 2;
183 mode = smbnhgets(pdata); pdata += 2;
184 sattr = smbnhgets(pdata); pdata += 2;
185 attr = smbnhgets(pdata); pdata += 2;
186 createtime = smbnhgetl(pdata); pdata += 4;
187 ofun = smbnhgets(pdata); pdata += 2;
188 createsize = smbnhgetl(pdata); pdata += 4;
189 timeout = smbnhgetl(pdata); pdata += 4;
190 pdata += 4;
191 USED(pdata);
192 if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
193 pr = SmbProcessResultFormat;
194 goto done;
195 }
196
197 smbloglock();
198 smblogprint(h->command, "flags 0x%.4ux", flags);
199 if (flags & SMB_OPEN_FLAGS_ADDITIONAL)
200 smblogprint(h->command, " additional");
201 if (flags & SMB_OPEN_FLAGS_OPLOCK)
202 smblogprint(h->command, " oplock");
203 if (flags & SMB_OPEN_FLAGS_OPBATCH)
204 smblogprint(h->command, " opbatch");
205 smblogprint(h->command, "\n");
206 smblogprint(h->command, "mode 0x%.4ux", mode);
207 switch ((mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK) {
208 case OREAD:
209 smblogprint(h->command, " OREAD");
210 break;
211 case OWRITE:
212 smblogprint(h->command, " OWRITE");
213 break;
214 case ORDWR:
215 smblogprint(h->command, " ORDWR");
216 break;
217 case OEXEC:
218 smblogprint(h->command, " OEXEC");
219 break;
220 }
221 switch ((mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK) {
222 case SMB_OPEN_MODE_SHARE_COMPATIBILITY:
223 smblogprint(h->command, " compatinility");
224 break;
225 case SMB_OPEN_MODE_SHARE_EXCLUSIVE:
226 smblogprint(h->command, " exclusive");
227 break;
228 case SMB_OPEN_MODE_SHARE_DENY_WRITE:
229 smblogprint(h->command, " deny write");
230 break;
231 case SMB_OPEN_MODE_SHARE_DENY_READOREXEC:
232 smblogprint(h->command, " deny readorxec");
233 break;
234 case SMB_OPEN_MODE_SHARE_DENY_NONE:
235 smblogprint(h->command, " deny none");
236 break;
237 }
238 if (mode & SMB_OPEN_MODE_WRITE_THROUGH)
239 smblogprint(h->command, " write through");
240 smblogprint(h->command, "\n");
241 smblogprint(h->command, "sattr 0x%.4ux", sattr);
242 smblogprintattr(h->command, sattr);
243 smblogprint(h->command, "\n");
244 smblogprint(h->command, "attr 0x%.4ux", attr);
245 smblogprintattr(h->command, attr);
246 smblogprint(h->command, "\n");
247 smblogprint(h->command, "createtime 0x%.8lux\n", createtime);
248 smblogprint(h->command, "ofun 0x%.4ux", ofun);
249 if (ofun & SMB_OFUN_NOEXIST_CREATE)
250 smblogprint(h->command, " noexistscreate");
251 else
252 smblogprint(h->command, " noexistfail");
253 switch ((ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK) {
254 case SMB_OFUN_EXIST_FAIL:
255 smblogprint(h->command, " existfail");
256 break;
257 case SMB_OFUN_EXIST_OPEN:
258 smblogprint(h->command, " existopen");
259 break;
260 case SMB_OFUN_EXIST_TRUNCATE:
261 smblogprint(h->command, " existtruncate");
262 break;
263 }
264 smblogprint(h->command, "\n");
265 smblogprint(h->command, "createsize 0x%.8lux\n", createsize);
266 smblogprint(h->command, "timeout 0x%.8lux\n", timeout);
267 smblogprint(h->command, "path %s\n", path);
268 smblogunlock();
269
270 t = smbidmapfind(s->tidmap, h->tid);
271 if (t == nil) {
272 smbseterror(s, ERRSRV, ERRinvtid);
273 goto errordone;
274 }
275
276 f = openfile(s, t, path, mode, attr, ofun, 0, createsize, &fid, &d, &action);
277 if (f == nil) {
278 pr = SmbProcessResultError;
279 goto done;
280 }
281 h->wordcount = 15;
282 if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixupoffset)
283 || !smbbufferputs(s->response, fid)
284 || !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
285 || !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
286 || !smbbufferputl(s->response, smbplan9length2size32(d->length))
287 || !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode)) // probbaly bogus
288 || !smbbufferputs(s->response, 0) // all files are files
289 || !smbbufferputs(s->response, 0) // pipe state
290 || !smbbufferputs(s->response, action)
291 || !smbbufferputl(s->response, 0) // fileID
292 || !smbbufferputs(s->response, 0)
293 || !smbbufferputs(s->response, 0)) { // bytecount 0
294 smbfileclose(s, f);
295 pr = SmbProcessResultMisc;
296 goto done;
297 }
298 if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
299 pr = smbchaincommand(s, h, andxoffsetfixupoffset, andxcommand, andxoffset, b);
300 else
301 pr = SmbProcessResultReply;
302 goto done;
303 errordone:
304 pr = SmbProcessResultError;
305 done:
306 free(path);
307 free(d);
308 return pr;
309 }
310
311 SmbProcessResult
smbcomopen(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)312 smbcomopen(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
313 {
314 uchar fmt;
315 char *path;
316 ushort mode, attr;
317 SmbTree *t;
318 ushort fid;
319 Dir *d = nil;
320 SmbFile *f;
321 SmbProcessResult pr;
322
323 if (!smbcheckwordcount("comopen", h, 2))
324 return SmbProcessResultFormat;
325 mode = smbnhgets(pdata);
326 attr = smbnhgets(pdata + 2);
327 if (!smbbuffergetb(b, &fmt)
328 || fmt != 4
329 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
330 pr = SmbProcessResultFormat;
331 goto done;
332 }
333 t = smbidmapfind(s->tidmap, h->tid);
334 if (t == nil) {
335 smbseterror(s, ERRSRV, ERRinvtid);
336 error:
337 pr = SmbProcessResultError;
338 goto done;
339 }
340 f = openfile(s, t, path, mode, attr,
341 SMB_OFUN_EXIST_OPEN << SMB_OFUN_EXIST_SHIFT,
342 0, 0, &fid, &d, nil);
343 if (f == nil)
344 goto error;
345 h->wordcount = 7;
346 if (!smbbufferputheader(s->response, h, &s->peerinfo)
347 || !smbbufferputs(s->response, fid)
348 || !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
349 || !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
350 || !smbbufferputl(s->response, smbplan9length2size32(d->length))
351 || !smbbufferputs(s->response, 2) // lies - this should be the actual access allowed
352 || !smbbufferputs(s->response, 0))
353 pr = SmbProcessResultMisc;
354 else
355 pr = SmbProcessResultReply;
356 done:
357 free(path);
358 free(d);
359 return pr;
360 }
361
362
363 /*
364 smb_com SMBcreate smb_com SMBcreate
365 smb_wct 3 smb_wct 1
366 smb_vwv[0] attribute smb_vwv[0] file handle
367 smb_vwv[1] time low smb_bcc 0
368 smb_vwv[2] time high
369 smb_bcc min = 2
370 smb_buf[] ASCII -- 04
371 file pathname
372 */
373
374 SmbProcessResult
smbcomcreate(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)375 smbcomcreate(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
376 {
377 int ofun, attr, mode;
378 long createtime;
379 char *path;
380 uchar fmt;
381 SmbFile *f;
382 SmbTree *t;
383 ushort fid;
384 SmbProcessResult pr;
385
386 path = nil;
387 if (!smbcheckwordcount("comcreate", h, 3))
388 return SmbProcessResultFormat;
389
390 smblogprint(h->command, "tid=%d\n", h->tid);
391 attr = smbnhgets(pdata); pdata += 2;
392 createtime = smbnhgetl(pdata);
393 if (!smbbuffergetb(b, &fmt) || fmt != 0x04 ||
394 !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)){
395 pr = SmbProcessResultError;
396 goto done;
397 }
398
399 smbloglock();
400 smblogprint(h->command, "path %s\n", path);
401 smblogprint(h->command, "attr 0x%.4ux", attr);
402 smblogprintattr(h->command, attr);
403 smblogprint(h->command, "\n");
404 smblogprint(h->command, "createtime 0x%.8lux\n", createtime);
405 smblogunlock();
406
407 t = smbidmapfind(s->tidmap, h->tid);
408 if (t == nil) {
409 pr = SmbProcessResultError;
410 goto done;
411 }
412
413 mode = (ORDWR<<SMB_OPEN_MODE_ACCESS_SHIFT) | // SFS: FIXME: should be OWRITE?
414 (SMB_OPEN_MODE_SHARE_EXCLUSIVE<<SMB_OPEN_MODE_SHARE_SHIFT);
415 ofun = SMB_OFUN_NOEXIST_CREATE|(SMB_OFUN_EXIST_FAIL<<SMB_OFUN_EXIST_SHIFT);
416 f = openfile(s, t, path, mode, attr, ofun, SMB_CO_FILE, 0, &fid, nil, nil);
417 if (f == nil) {
418 pr = SmbProcessResultError;
419 goto done;
420 }
421
422 h->wordcount = 1; // SFS: FIXME: unsure of this constant, maybe should be 3
423 if (!smbbufferputheader(s->response, h, &s->peerinfo)
424 || !smbbufferputs(s->response, fid)
425 || !smbbufferputs(s->response, 0)){ // bytecount 0
426 pr = SmbProcessResultMisc;
427 goto done;
428 }
429 pr = SmbProcessResultReply;
430 goto done;
431
432 done:
433 free(path);
434 return pr;
435 }
436
437
438 typedef struct SmbSblut {
439 char *s;
440 ulong mask;
441 } SmbSblut;
442
443 static SmbSblut dasblut[] = {
444 { "SMB_DA_SPECIFIC_READ_DATA", SMB_DA_SPECIFIC_READ_DATA },
445 { "SMB_DA_SPECIFIC_WRITE_DATA", SMB_DA_SPECIFIC_WRITE_DATA },
446 { "SMB_DA_SPECIFIC_APPEND_DATA", SMB_DA_SPECIFIC_APPEND_DATA },
447 { "SMB_DA_SPECIFIC_READ_EA", SMB_DA_SPECIFIC_READ_EA },
448 { "SMB_DA_SPECIFIC_WRITE_EA", SMB_DA_SPECIFIC_WRITE_EA },
449 { "SMB_DA_SPECIFIC_EXECUTE", SMB_DA_SPECIFIC_EXECUTE },
450 { "SMB_DA_SPECIFIC_DELETE_CHILD", SMB_DA_SPECIFIC_DELETE_CHILD },
451 { "SMB_DA_SPECIFIC_READ_ATTRIBUTES", SMB_DA_SPECIFIC_READ_ATTRIBUTES },
452 { "SMB_DA_SPECIFIC_WRITE_ATTRIBUTES", SMB_DA_SPECIFIC_WRITE_ATTRIBUTES },
453 { "SMB_DA_STANDARD_DELETE_ACCESS", SMB_DA_STANDARD_DELETE_ACCESS },
454 { "SMB_DA_STANDARD_READ_CONTROL_ACCESS", SMB_DA_STANDARD_READ_CONTROL_ACCESS },
455 { "SMB_DA_STANDARD_WRITE_DAC_ACCESS", SMB_DA_STANDARD_WRITE_DAC_ACCESS },
456 { "SMB_DA_STANDARD_WRITE_OWNER_ACCESS", SMB_DA_STANDARD_WRITE_OWNER_ACCESS },
457 { "SMB_DA_STANDARD_SYNCHRONIZE_ACCESS", SMB_DA_STANDARD_SYNCHRONIZE_ACCESS },
458 { "SMB_DA_GENERIC_ALL_ACCESS", SMB_DA_GENERIC_ALL_ACCESS },
459 { "SMB_DA_GENERIC_EXECUTE_ACCESS", SMB_DA_GENERIC_EXECUTE_ACCESS },
460 { "SMB_DA_GENERIC_WRITE_ACCESS", SMB_DA_GENERIC_WRITE_ACCESS },
461 { "SMB_DA_GENERIC_READ_ACCESS", SMB_DA_GENERIC_READ_ACCESS },
462 { 0 }
463 };
464
465 static SmbSblut efasblut[] = {
466 { "SMB_ATTR_READ_ONLY", SMB_ATTR_READ_ONLY },
467 { "SMB_ATTR_HIDDEN", SMB_ATTR_HIDDEN },
468 { "SMB_ATTR_SYSTEM", SMB_ATTR_SYSTEM },
469 { "SMB_ATTR_DIRECTORY", SMB_ATTR_DIRECTORY },
470 { "SMB_ATTR_ARCHIVE", SMB_ATTR_ARCHIVE },
471 { "SMB_ATTR_NORMAL", SMB_ATTR_NORMAL },
472 { "SMB_ATTR_COMPRESSED", SMB_ATTR_COMPRESSED },
473 { "SMB_ATTR_TEMPORARY", SMB_ATTR_TEMPORARY },
474 { "SMB_ATTR_WRITETHROUGH", SMB_ATTR_WRITETHROUGH },
475 { "SMB_ATTR_NO_BUFFERING", SMB_ATTR_NO_BUFFERING },
476 { "SMB_ATTR_RANDOM_ACCESS", SMB_ATTR_RANDOM_ACCESS },
477 { 0 }
478 };
479
480 static SmbSblut sasblut[] = {
481 { "SMB_SA_SHARE_READ", SMB_SA_SHARE_READ },
482 { "SMB_SA_SHARE_WRITE", SMB_SA_SHARE_WRITE },
483 { "SMB_SA_SHARE_DELETE", SMB_SA_SHARE_DELETE },
484 { "SMB_SA_NO_SHARE", SMB_SA_NO_SHARE },
485 { 0 }
486 };
487
488 static SmbSblut cosblut[] = {
489 { "SMB_CO_DIRECTORY", SMB_CO_DIRECTORY },
490 { "SMB_CO_WRITETHROUGH", SMB_CO_WRITETHROUGH },
491 { "SMB_CO_SEQUENTIAL_ONLY", SMB_CO_SEQUENTIAL_ONLY },
492 { "SMB_CO_FILE", SMB_CO_FILE },
493 { "SMB_CO_NO_EA_KNOWLEDGE", SMB_CO_NO_EA_KNOWLEDGE },
494 { "SMB_CO_EIGHT_DOT_THREE_ONLY", SMB_CO_EIGHT_DOT_THREE_ONLY },
495 { "SMB_CO_RANDOM_ACCESS", SMB_CO_RANDOM_ACCESS },
496 { "SMB_CO_DELETE_ON_CLOSE", SMB_CO_DELETE_ON_CLOSE },
497 { 0 }
498 };
499
500 static SmbSlut cdslut[] = {
501 { "SMB_CD_SUPERCEDE", SMB_CD_SUPERCEDE },
502 { "SMB_CD_OPEN", SMB_CD_OPEN },
503 { "SMB_CD_CREATE", SMB_CD_CREATE },
504 { "SMB_CD_OPEN_IF", SMB_CD_OPEN_IF },
505 { "SMB_CD_OVERWRITE", SMB_CD_OVERWRITE },
506 { "SMB_CD_OVERWRITE_IF", SMB_CD_OVERWRITE_IF },
507 { 0 }
508 };
509
510 static void
smbsblutlogprint(uchar cmd,SmbSblut * sblut,ulong mask)511 smbsblutlogprint(uchar cmd, SmbSblut *sblut, ulong mask)
512 {
513 while (sblut->s) {
514 if (mask && (sblut->mask & mask) || (mask == 0 && sblut->mask == 0))
515 smblogprint(cmd, " %s", sblut->s);
516 sblut++;
517 }
518 }
519
520 SmbProcessResult
smbcomntcreateandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)521 smbcomntcreateandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
522 {
523 uchar andxcommand;
524 ushort andxoffset;
525 char *path = nil;
526 SmbProcessResult pr;
527 ulong namelength;
528 ulong flags;
529 ulong rootdirectoryfid, desiredaccess;
530 uvlong allocationsize;
531 ulong extfileattributes, shareaccess, createdisposition, createoptions, impersonationlevel;
532 uchar securityflags;
533 int p9mode;
534 int sharemode;
535 ushort mode;
536 SmbTree *t;
537 ushort ofun;
538 SmbFile *f;
539 ushort fid;
540 Dir *d = nil;
541 ushort action;
542 uvlong mtime;
543 ulong andxoffsetfixup;
544
545 if (!smbcheckwordcount("comntcreateandx", h, 24))
546 return SmbProcessResultFormat;
547
548 andxcommand = *pdata++;
549 pdata++;
550 andxoffset = smbnhgets(pdata); pdata += 2;
551 pdata++;
552 namelength = smbnhgets(pdata); pdata += 2;
553 flags = smbnhgetl(pdata); pdata += 4;
554 rootdirectoryfid = smbnhgetl(pdata); pdata += 4;
555 desiredaccess = smbnhgetl(pdata); pdata += 4;
556 allocationsize = smbnhgetv(pdata); pdata += 8;
557 extfileattributes = smbnhgetl(pdata); pdata += 4;
558 shareaccess = smbnhgetl(pdata); pdata += 4;
559 createdisposition = smbnhgetl(pdata); pdata += 4;
560 createoptions = smbnhgetl(pdata); pdata += 4;
561 impersonationlevel = smbnhgetl(pdata); pdata += 4;
562 securityflags = *pdata++;
563 USED(pdata);
564
565 if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
566 pr = SmbProcessResultFormat;
567 goto done;
568 }
569
570 smblogprint(h->command, "namelength %d\n", namelength);
571 smblogprint(h->command, "flags 0x%.8lux\n", flags);
572 smblogprint(h->command, "rootdirectoryfid %lud\n", rootdirectoryfid);
573 smblogprint(h->command, "desiredaccess 0x%.8lux", desiredaccess);
574 smbsblutlogprint(h->command, dasblut, desiredaccess);
575 smblogprint(h->command, "\n");
576 smblogprint(h->command, "allocationsize %llud\n", allocationsize);
577 smblogprint(h->command, "extfileattributes 0x%.8lux", extfileattributes);
578 smbsblutlogprint(h->command, efasblut, extfileattributes);
579 smblogprint(h->command, "\n");
580 smblogprint(h->command, "shareaccess 0x%.8lux", shareaccess);
581 smbsblutlogprint(h->command, sasblut, shareaccess);
582 smblogprint(h->command, "\n");
583 smblogprint(h->command, "createdisposition 0x%.8lux %s\n",
584 createdisposition, smbrevslut(cdslut, createdisposition));
585 smblogprint(h->command, "createoptions 0x%.8lux", createoptions);
586 smbsblutlogprint(h->command, cosblut, createoptions);
587 smblogprint(h->command, "\n");
588 smblogprint(h->command, "impersonationlevel 0x%.8lux\n", impersonationlevel);
589 smblogprint(h->command, "securityflags 0x%.2ux\n", securityflags);
590 smblogprint(h->command, "path %s\n", path);
591
592 if (rootdirectoryfid != 0) {
593 smblogprint(-1, "smbcomntcreateandx: fid relative not implemented\n");
594 goto unimp;
595 }
596
597 if (desiredaccess & SMB_DA_GENERIC_MASK)
598 switch (desiredaccess & SMB_DA_GENERIC_MASK){
599 case SMB_DA_GENERIC_READ_ACCESS:
600 p9mode = OREAD;
601 break;
602 case SMB_DA_GENERIC_WRITE_ACCESS:
603 p9mode = OWRITE;
604 break;
605 case SMB_DA_GENERIC_ALL_ACCESS:
606 p9mode = ORDWR;
607 break;
608 case SMB_DA_GENERIC_EXECUTE_ACCESS:
609 p9mode = OEXEC;
610 break;
611 default:
612 p9mode = OREAD;
613 break;
614 }
615 else
616 if (desiredaccess & SMB_DA_SPECIFIC_READ_DATA)
617 if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA))
618 p9mode = ORDWR;
619 else
620 p9mode = OREAD;
621 else if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA))
622 p9mode = ORDWR;
623 else
624 p9mode = OREAD;
625
626 if (shareaccess == SMB_SA_NO_SHARE)
627 sharemode = SMB_OPEN_MODE_SHARE_EXCLUSIVE;
628 else if (shareaccess & (SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE) ==
629 (SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE))
630 sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE;
631 else if (shareaccess & SMB_SA_SHARE_READ)
632 sharemode = SMB_OPEN_MODE_SHARE_DENY_WRITE;
633 else if (shareaccess & SMB_SA_SHARE_WRITE)
634 sharemode = SMB_OPEN_MODE_SHARE_DENY_READOREXEC;
635 else
636 sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE;
637
638 mode = (sharemode << SMB_OPEN_MODE_SHARE_SHIFT) | (p9mode << SMB_OPEN_MODE_ACCESS_SHIFT);
639
640 switch (createdisposition) {
641 default:
642 smblogprint(-1, "smbcomntcreateandx: createdisposition 0x%.8lux not implemented\n", createdisposition);
643 goto unimp;
644 case SMB_CD_OPEN:
645 ofun = SMB_OFUN_EXIST_OPEN;
646 break;
647 case SMB_CD_CREATE:
648 ofun = SMB_OFUN_EXIST_FAIL | SMB_OFUN_NOEXIST_CREATE;
649 break;
650 case SMB_CD_OPEN_IF:
651 ofun = SMB_OFUN_EXIST_OPEN | SMB_OFUN_NOEXIST_CREATE;
652 break;
653 case SMB_CD_OVERWRITE:
654 ofun = SMB_OFUN_EXIST_TRUNCATE;
655 break;
656 case SMB_CD_OVERWRITE_IF:
657 ofun = SMB_OFUN_EXIST_TRUNCATE | SMB_OFUN_NOEXIST_CREATE;
658 break;
659 }
660
661 t = smbidmapfind(s->tidmap, h->tid);
662 if (t == nil) {
663 smbseterror(s, ERRSRV, ERRinvtid);
664 pr = SmbProcessResultError;
665 goto done;
666 }
667
668 f = openfile(s, t, path, mode, extfileattributes, ofun, createoptions, allocationsize, &fid, &d, &action);
669
670 if (f == nil) {
671 pr = SmbProcessResultError;
672 goto done;
673 }
674
675 h->wordcount = 42;
676 mtime = smbplan9time2time(d->mtime);
677 if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
678 || !smbbufferputb(s->response, 0) // oplocks? pah
679 || !smbbufferputs(s->response, fid)
680 || !smbbufferputl(s->response, action)
681 || !smbbufferputv(s->response, mtime)
682 || !smbbufferputv(s->response, smbplan9time2time(d->atime))
683 || !smbbufferputv(s->response, mtime)
684 || !smbbufferputv(s->response, mtime)
685 || !smbbufferputl(s->response, smbplan9mode2dosattr(d->mode))
686 || !smbbufferputv(s->response, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
687 || !smbbufferputv(s->response, d->length)
688 || !smbbufferputbytes(s->response, nil, 4)
689 || !smbbufferputb(s->response, (d->qid.type & QTDIR) != 0)
690 || !smbbufferputbytes(s->response, nil, 8)
691 || !smbbufferputs(s->response, 0)) {
692 pr = SmbProcessResultMisc;
693 goto done;
694 }
695
696 if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
697 pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
698 else
699 pr = SmbProcessResultReply;
700
701 goto done;
702
703 unimp:
704 pr = SmbProcessResultUnimp;
705
706 done:
707 free(path);
708 free(d);
709
710 return pr;
711 }
712
713