Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "headers.h"
2
 
3
static void
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 *
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
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
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
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
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
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