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 SmbProcessResult
4
query(SmbSession *s, char *cmdname, char *filename, ushort infolevel, vlong cbo, Dir *d)
5
{
6
	vlong ntatime, ntmtime;
7
	ushort dosmode;
8
	ulong fnlfixupoffset;
9
	vlong allocsize;
10
 
11
	if (d == nil) {
12
		smbseterror(s, ERRDOS, ERRbadfile);
13
		return SmbProcessResultError;
14
	}
15
 
16
	switch (infolevel) {
17
	case SMB_QUERY_FILE_BASIC_INFO:
18
		ntatime = smbplan9time2time(d->atime);
19
		ntmtime = smbplan9time2time(d->mtime);
20
		dosmode = smbplan9mode2dosattr(d->mode);
21
 
22
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_BASIC_INFO\n");
23
		translogprint(s->transaction.in.setup[0], "REPLY:\n");
24
		translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
25
		translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
26
		translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
27
 
28
		if (!smbbufferputv(s->transaction.out.data, ntmtime)
29
			|| !smbbufferputv(s->transaction.out.data, ntatime)
30
			|| !smbbufferputv(s->transaction.out.data, ntmtime)
31
			|| !smbbufferputv(s->transaction.out.data, ntmtime)
32
			|| !smbbufferputl(s->transaction.out.data, dosmode))
33
			return SmbProcessResultMisc;
34
		break;
35
	case SMB_QUERY_FILE_ALL_INFO:
36
		ntatime = smbplan9time2time(d->atime);
37
		ntmtime = smbplan9time2time(d->mtime);
38
		dosmode = smbplan9mode2dosattr(d->mode);
39
		allocsize = (d->length + (1 << smbglobals.l2allocationsize) - 1) & ~((1 << smbglobals.l2allocationsize) - 1);
40
 
41
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_ALL_INFO\n");
42
		translogprint(s->transaction.in.setup[0], "REPLY:\n");
43
		translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
44
		translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
45
		translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
46
		translogprint(s->transaction.in.setup[0], "allocsize=%d\n", allocsize);
47
		translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->mode & DMDIR) != 0);
48
 
49
		if (!smbbufferputv(s->transaction.out.data, ntmtime)
50
			|| !smbbufferputv(s->transaction.out.data, ntatime)
51
			|| !smbbufferputv(s->transaction.out.data, ntmtime)
52
			|| !smbbufferputv(s->transaction.out.data, ntmtime)
53
			|| !smbbufferputs(s->transaction.out.data, dosmode)
54
			|| !smbbufferputbytes(s->transaction.out.data, nil, 6)
55
			|| !smbbufferputv(s->transaction.out.data, allocsize)
56
			|| !smbbufferputv(s->transaction.out.data, d->length)
57
			|| !smbbufferputl(s->transaction.out.data, 0)		// hard links - ha
58
			|| !smbbufferputb(s->transaction.out.data, 0)		// TODO delete pending
59
			|| !smbbufferputb(s->transaction.out.data, (d->mode & DMDIR) != 0)
60
			|| !smbbufferputv(s->transaction.out.data, d->qid.path)
61
			|| !smbbufferputl(s->transaction.out.data, 0)		// EA size
62
			|| !smbbufferputl(s->transaction.out.data, (dosmode & SMB_ATTR_READ_ONLY) ? 0xa1 : 0x1a7)
63
			|| !smbbufferputv(s->transaction.out.data, cbo)
64
			|| !smbbufferputs(s->transaction.out.data, dosmode)
65
			|| !smbbufferputl(s->transaction.out.data, 0))	// alignment
66
			return SmbProcessResultMisc;
67
		fnlfixupoffset = smbbufferwriteoffset(s->transaction.out.data);
68
		if (!smbbufferputl(s->transaction.out.data, 0)
69
		    || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_REVPATH, filename)
70
		    || !smbbufferfixuprelativel(s->transaction.out.data, fnlfixupoffset))
71
			return SmbProcessResultMisc;
72
		break;
73
	case SMB_QUERY_FILE_STANDARD_INFO:
74
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STANDARD_INFO\n");
75
		translogprint(s->transaction.in.setup[0], "REPLY:\n");
76
		translogprint(s->transaction.in.setup[0], "length=%lld", d->length);
77
		translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->qid.type & QTDIR) != 0);
78
 
79
		if (!smbbufferputv(s->transaction.out.data, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
80
			|| !smbbufferputv(s->transaction.out.data, d->length)
81
			|| !smbbufferputl(s->transaction.out.data, 1)
82
			|| !smbbufferputb(s->transaction.out.data, 0)
83
			|| !smbbufferputb(s->transaction.out.data, (d->qid.type & QTDIR) != 0))
84
			return SmbProcessResultMisc;
85
		break;
86
	case SMB_QUERY_FILE_EA_INFO:
87
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_EA_INFO\n");
88
		translogprint(s->transaction.in.setup[0], "REPLY:\n");
89
		translogprint(s->transaction.in.setup[0], "ea_len=0\n");
90
		if (!smbbufferputl(s->transaction.out.data, 0))
91
			return SmbProcessResultMisc;
92
		break;
93
	case SMB_QUERY_FILE_STREAM_INFO:
94
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STREAM_INFO\n");
95
		translogprint(s->transaction.in.setup[0], "REPLY: failed\n");
96
		/* don't do it, never will */
97
		goto unknownlevel;
98
	default:
99
		smblogprint(-1, "smbtrans2query%sinformation: infolevel 0x%.4ux not implemented\n", cmdname, infolevel);
100
	unknownlevel:
101
		translogprint(s->transaction.in.setup[0], "[not supported]\n");
102
		smbseterror(s, ERRDOS, ERRunknownlevel);
103
		return SmbProcessResultError;
104
	}
105
	return SmbProcessResultReply;
106
}
107
 
108
SmbProcessResult
109
smbtrans2querypathinformation(SmbSession *s, SmbHeader *h)
110
{
111
	SmbTree *t;
112
	SmbBuffer *b = nil;
113
	SmbProcessResult pr;
114
	ushort infolevel;
115
	Dir *d;
116
	char *path = nil;
117
	char *fullpath;
118
 
119
	t = smbidmapfind(s->tidmap, h->tid);
120
	if (t == nil) {
121
		smbseterror(s, ERRSRV, ERRinvtid);
122
		pr = SmbProcessResultError;
123
		goto done;
124
	}
125
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
126
	if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
127
		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
128
		pr = SmbProcessResultMisc;
129
		goto done;
130
	}
131
	translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
132
	translogprint(s->transaction.in.setup[0], "path %s\n", path);
133
	fullpath = nil;
134
	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
135
	translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);
136
	d = dirstat(fullpath);
137
	pr = query(s, "path", path, infolevel, 0, d);
138
	free(d);
139
	free(fullpath);
140
done:
141
	free(path);
142
	smbbufferfree(&b);
143
	return pr;
144
}
145
 
146
SmbProcessResult
147
smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h)
148
{
149
	SmbTree *t;
150
	SmbFile *f;
151
	SmbBuffer *b = nil;
152
	SmbProcessResult pr;
153
	ushort fid;
154
	ushort infolevel;
155
	vlong o;
156
	Dir *d;
157
 
158
	t = smbidmapfind(s->tidmap, h->tid);
159
	if (t == nil) {
160
		smbseterror(s, ERRSRV, ERRinvtid);
161
		pr = SmbProcessResultError;
162
		goto done;
163
	}
164
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
165
	if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
166
		pr = SmbProcessResultMisc;
167
		goto done;
168
	}
169
	translogprint(s->transaction.in.setup[0], "fid 0x%.4ux\n", fid);
170
	translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
171
	f = smbidmapfind(s->fidmap, fid);
172
	if (f == nil) {
173
		smbseterror(s, ERRDOS, ERRbadfid);
174
		pr = SmbProcessResultError;
175
		goto done;
176
	}
177
	if(f->fd >= 0){
178
		o = seek(f->fd, 0, 1);
179
		d = dirfstat(f->fd);
180
	} else {
181
		char *fullpath = nil;
182
 
183
		o = 0;
184
		smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name);
185
		d = dirstat(fullpath);
186
		free(fullpath);
187
	}
188
	pr = query(s, "file", f->name, infolevel, o, d);
189
	free(d);
190
done:
191
	smbbufferfree(&b);
192
	return pr;
193
}
194
 
195
SmbProcessResult
196
smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h)
197
{
198
	SmbTree *t;
199
	ushort infolevel;
200
	SmbBuffer *b;
201
	SmbProcessResult pr;
202
	ulong fixup;
203
	ulong vnbase;
204
 
205
	t = smbidmapfind(s->tidmap, h->tid);
206
	if (t == nil) {
207
		smbseterror(s, ERRSRV, ERRinvtid);
208
		pr = SmbProcessResultError;
209
		goto done;
210
	}
211
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
212
	if (!smbbuffergets(b, &infolevel)) {
213
	misc:
214
		pr = SmbProcessResultMisc;
215
		goto done;
216
	}
217
	pr = SmbProcessResultReply;
218
	switch (infolevel) {
219
	case SMB_INFO_ALLOCATION:
220
		translogprint(s->transaction.in.setup[0], "SMB_INFO_ALLOCATION\n");
221
		if (!smbbufferputl(s->transaction.out.data, 0)
222
			|| !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
223
			|| !smbbufferputl(s->transaction.out.data, 0xffffffff)
224
			|| !smbbufferputl(s->transaction.out.data, 0xffffffff)
225
			|| !smbbufferputs(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
226
			goto misc;
227
		break;
228
	case SMB_INFO_VOLUME:
229
		translogprint(s->transaction.in.setup[0], "SMB_INFO_VOLUME\n");
230
		if (!smbbufferputl(s->transaction.out.data, 0xdeadbeef)
231
			|| !smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name))
232
			goto misc;
233
		break;
234
	case SMB_QUERY_FS_VOLUME_INFO:
235
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_VOLUME_INFO\n");
236
		if (!smbbufferputv(s->transaction.out.data, 0)
237
			|| !smbbufferputl(s->transaction.out.data, 0xdeadbeef))
238
			goto misc;
239
		fixup = smbbufferwriteoffset(s->transaction.out.data);
240
		if (!smbbufferputl(s->transaction.out.data, 0)
241
			|| !smbbufferputs(s->transaction.out.data, 0))
242
			goto misc;
243
		vnbase = smbbufferwriteoffset(s->transaction.out.data);
244
		if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name)
245
			|| !smbbufferfixupl(s->transaction.out.data, fixup,
246
				smbbufferwriteoffset(s->transaction.out.data) - vnbase))
247
			goto misc;
248
		break;
249
	case SMB_QUERY_FS_SIZE_INFO:
250
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_SIZE_INFO\n");
251
		if (!smbbufferputv(s->transaction.out.data, 0LL)
252
			|| !smbbufferputv(s->transaction.out.data, 0LL)
253
			|| !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
254
			|| !smbbufferputl(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
255
			goto misc;
256
		break;
257
	case SMB_QUERY_FS_ATTRIBUTE_INFO:
258
		translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_ATTRIBUTE_INFO\n");
259
		if (!smbbufferputl(s->transaction.out.data, 3)
260
			|| !smbbufferputl(s->transaction.out.data, 255))
261
			goto misc;
262
		fixup = smbbufferwriteoffset(s->transaction.out.data);
263
		if (!smbbufferputl(s->transaction.out.data, 0)
264
			|| !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_UNTERMINATED, smbglobals.serverinfo.nativelanman)
265
			|| !smbbufferfixuprelativel(s->transaction.out.data, fixup))
266
			goto misc;
267
		break;
268
	default:
269
		smblogprint(-1, "smbtrans2queryfsinformation: infolevel 0x%.4ux not implemented\n", infolevel);
270
		smbseterror(s, ERRDOS, ERRunknownlevel);
271
		pr = SmbProcessResultError;
272
	}
273
done:
274
	smbbufferfree(&b);
275
	return pr;
276
}