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
#include <pool.h>
3
 
4
void
5
smbsearchfree(SmbSearch **searchp)
6
{
7
	SmbSearch *search = *searchp;
8
	if (search) {
9
		smbdircachefree(&search->dc);
10
		free(search->rep);
11
		free(search);
12
		*searchp = nil;
13
	}
14
}
15
 
16
void
17
smbsearchclose(SmbSession *s, SmbSearch *search)
18
{
19
	if (search) {
20
		smblogprintif(smbglobals.log.sids, "smbsearchclose: tid 0x%.4ux sid 0x%.4ux\n", search->t->id, search->id);
21
		smbidmapremove(s->sidmap, search);
22
		smbsearchfree(&search);
23
	}
24
}
25
 
26
void
27
smbsearchclosebyid(SmbSession *s, ushort sid)
28
{
29
	smbsearchclose(s,  smbidmapfind(s->sidmap, sid));
30
}
31
 
32
SmbSearch *
33
smbsearchnew(SmbSession *s, SmbDirCache *dc, Reprog *r, SmbTree *t)
34
{
35
	SmbSearch *search;
36
	if (s->sidmap == nil)
37
		s->sidmap = smbidmapnew();
38
	search = smbemalloc(sizeof(SmbSearch));
39
	smbidmapadd(s->sidmap, search);
40
	search->dc = dc;
41
	search->rep = r;
42
	search->t = t;
43
	smblogprintif(smbglobals.log.sids, "smbsearchnew: 0x%.4ux\n", search->id);
44
	return search;
45
}
46
 
47
static int
48
standardflatten(SmbSession *s, SmbBuffer *b, Dir *d, ulong *nameoffsetp)
49
{
50
	ushort mdate, mtime;
51
	ushort adate, atime;
52
	ushort fnlfixupoffset;
53
 
54
	smbplan9time2datetime(d->mtime, s->tzoff, &mdate, &mtime);
55
	smbplan9time2datetime(d->atime, s->tzoff, &adate, &atime);
56
	if (!smbbufferputs(b, mdate)
57
		|| !smbbufferputs(b, mtime)
58
		|| !smbbufferputs(b, adate)
59
		|| !smbbufferputs(b, atime)
60
		|| !smbbufferputs(b, mdate)
61
		|| !smbbufferputs(b, mtime)
62
		|| !smbbufferputl(b, d->length)
63
		|| !smbbufferputl(b, 512)			// ha
64
		|| !smbbufferputs(b, (d->qid.type & QTDIR) ? 0x10 : 0))
65
		return 0;
66
	fnlfixupoffset = smbbufferwriteoffset(b);
67
	if (!smbbufferputs(b, 0))
68
		return 0;
69
	*nameoffsetp = smbbufferwriteoffset(b);
70
	if (!smbbufferputstring(b, &s->peerinfo, 0, d->name))
71
		return 0;
72
	return smbbufferfixuprelatives(b, fnlfixupoffset);
73
}
74
 
75
static int
76
findbothflatten(SmbBuffer *b, SmbPeerInfo *p, Dir *d, ulong resumekey, ulong *nameoffsetp)
77
{
78
	vlong mtime, atime;
79
	ulong fixup;
80
 
81
	fixup = smbbufferwriteoffset(b);
82
	mtime = smbplan9time2time(d->mtime);
83
	atime = smbplan9time2time(d->atime);
84
poolcheck(mainmem);
85
	if (!smbbufferputl(b, 0)
86
		|| !smbbufferputl(b, resumekey)
87
		|| !smbbufferputv(b, mtime)
88
		|| !smbbufferputv(b, atime)
89
		|| !smbbufferputv(b, mtime)
90
		|| !smbbufferputv(b, mtime)
91
		|| !smbbufferputv(b, d->length)
92
		|| !smbbufferputv(b, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))			// ha
93
		|| !smbbufferputl(b, (d->qid.type & QTDIR) ? 0x10 : 0x80)
94
		|| !smbbufferputl(b, smbstringlen(p, d->name))
95
		|| !smbbufferputl(b, 0)
96
		|| !smbbufferputb(b, 0)
97
		|| !smbbufferputb(b, 0)
98
		|| !smbbufferfill(b, 0, 24))
99
		return 0;
100
poolcheck(mainmem);
101
	*nameoffsetp = smbbufferwriteoffset(b);
102
	if (!smbbufferputstring(b, p, 0, d->name) || !smbbufferalignl2(b, 2))
103
		return 0;
104
poolcheck(mainmem);
105
	return smbbufferfixuprelativeinclusivel(b, fixup);
106
}
107
 
108
static void
109
populate(SmbSession *s, SmbDirCache *dc, Reprog *r, ushort informationlevel, ushort flags, ushort scount,
110
	ushort *ep, ulong *nameoffsetp)
111
{
112
	ushort e;
113
	ulong nameoffset;
114
	e = 0;
115
	nameoffset = 0;
116
	while (dc->i < dc->n && e < scount) {
117
		ulong backup;
118
		int rv;
119
 
120
		if (!smbmatch(dc->buf[dc->i].name, r)) {
121
			dc->i++;
122
			continue;
123
		}
124
		rv = 0;
125
		backup = smbbufferwriteoffset(s->transaction.out.data);
126
		switch (informationlevel) {
127
		case SMB_INFO_STANDARD:
128
			if (flags & SMB_FIND_RETURN_RESUME_KEYS) {
129
				if (!smbbufferputl(s->transaction.out.data, dc->i)) {
130
					rv = 0;
131
					break;
132
				}
133
			}
134
			rv = standardflatten(s, s->transaction.out.data, dc->buf + dc->i, &nameoffset);
135
			break;
136
		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
137
			rv = findbothflatten(s->transaction.out.data, &s->peerinfo, dc->buf + dc->i, dc->i, &nameoffset);
138
			break;
139
		}
140
		if (rv == 0) {
141
			smbbufferwritebackup(s->transaction.out.data, backup);
142
			break;
143
		}
144
		dc->i++;
145
		e++;
146
	}
147
	*ep = e;
148
	*nameoffsetp = nameoffset;
149
}
150
 
151
SmbProcessResult
152
smbtrans2findfirst2(SmbSession *s, SmbHeader *h)
153
{
154
	SmbBuffer *b;
155
	char *pattern = nil;
156
	char *dir = nil;
157
	char *name = nil;
158
	ushort searchattributes, searchcount, flags, informationlevel;
159
	ulong searchstoragetype;
160
	SmbDirCache *dc = nil;
161
	ushort e;
162
	ulong nameoffset;
163
	ushort eos;
164
	SmbSearch *search;
165
	SmbProcessResult pr;
166
	Reprog *r = nil;
167
	SmbTree *t;
168
	int debug;
169
 
170
	debug = smboptable[h->command].debug
171
		|| smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug
172
		|| smbglobals.log.find;
173
poolcheck(mainmem);
174
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
175
	if (!smbbuffergets(b, &searchattributes)
176
		|| !smbbuffergets(b, &searchcount)
177
		|| !smbbuffergets(b, &flags)
178
		|| !smbbuffergets(b, &informationlevel)
179
		|| !smbbuffergetl(b, &searchstoragetype)
180
		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) {
181
		pr = SmbProcessResultFormat;
182
		goto done;
183
	}
184
	smbloglock();
185
	smblogprintif(debug, "searchattributes: 0x%.4ux\n", searchattributes);
186
	smblogprintif(debug, "searchcount: 0x%.4ux\n", searchcount);
187
	smblogprintif(debug, "flags: 0x%.4ux\n", flags);
188
	smblogprintif(debug, "informationlevel: 0x%.4ux\n", informationlevel);
189
	smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype);
190
	smblogprintif(debug, "pattern: %s\n", pattern);
191
	smblogunlock();
192
	smbpathsplit(pattern, &dir, &name);
193
	if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
194
		smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4ux not implemented\n", informationlevel);
195
		smbseterror(s, ERRDOS, ERRunknownlevel);
196
		pr = SmbProcessResultError;
197
		goto done;
198
	}
199
 
200
	t = smbidmapfind(s->tidmap, h->tid);
201
	if (t == nil) {
202
		smbseterror(s, ERRSRV, ERRinvtid);
203
		pr = SmbProcessResultError;
204
		goto done;
205
	}
206
 
207
	dc = smbmkdircache(t, dir);
208
	if (dc == nil) {
209
		smbseterror(s, ERRDOS, ERRnoaccess);
210
		pr = SmbProcessResultError;
211
		goto done;
212
	}
213
poolcheck(mainmem);
214
	r = smbmkrep(name);
215
	populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset);
216
poolcheck(mainmem);
217
	eos = dc->i >= dc->n;
218
	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
219
		smbdircachefree(&dc);
220
poolcheck(mainmem);
221
	if (dc) {
222
		/* create a search handle */
223
		search = smbsearchnew(s, dc, r, t);
224
		r = nil;
225
		dc = nil;
226
	}
227
	else
228
		search = nil;
229
	smbbufferputs(s->transaction.out.parameters, search ? search->id : 0);
230
	smbbufferputs(s->transaction.out.parameters, e);
231
	smbbufferputs(s->transaction.out.parameters, eos);
232
	smbbufferputs(s->transaction.out.parameters, 0);
233
	smbbufferputs(s->transaction.out.parameters, nameoffset);
234
	pr = SmbProcessResultReply;
235
done:
236
	smbbufferfree(&b);
237
	free(pattern);
238
	free(dir);
239
	free(name);
240
	smbdircachefree(&dc);
241
	free(r);
242
	return pr;
243
}
244
 
245
SmbProcessResult
246
smbtrans2findnext2(SmbSession *s, SmbHeader *h)
247
{
248
	SmbBuffer *b;
249
	int debug;
250
	ushort sid, scount, infolevel;
251
	ulong resumekey;
252
	ushort flags;
253
	char *filename = nil;
254
	SmbProcessResult pr;
255
	ushort e;
256
	ulong nameoffset;
257
	ushort eos;
258
	SmbTree *t;
259
	SmbSearch *search;
260
 
261
	debug = smboptable[h->command].debug
262
		|| smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug
263
		|| smbglobals.log.find;
264
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
265
	if (!smbbuffergets(b, &sid)
266
		|| !smbbuffergets(b, &scount)
267
		|| !smbbuffergets(b, &infolevel)
268
		|| !smbbuffergetl(b, &resumekey)
269
		|| !smbbuffergets(b, &flags)
270
		|| !smbbuffergetstring(b, h, 0, &filename)) {
271
		pr = SmbProcessResultFormat;
272
		goto done;
273
	}
274
	smblogprintif(debug,
275
		"smbtrans2findnext2: sid %d scount %d infolevel 0x%.4ux resumekey %lud flags 0x%.4ux filename %s\n",
276
		sid, scount, infolevel, resumekey, flags, filename);
277
 
278
	if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
279
		smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4ux not implemented\n", infolevel);
280
		smbseterror(s, ERRDOS, ERRunknownlevel);
281
		pr = SmbProcessResultError;
282
		goto done;
283
	}
284
 
285
	t = smbidmapfind(s->tidmap, h->tid);
286
	if (t == nil) {
287
		smbseterror(s, ERRSRV, ERRinvtid);
288
		pr = SmbProcessResultError;
289
		goto done;
290
	}
291
 
292
	search = smbidmapfind(s->sidmap, sid);
293
	if (search == nil) {
294
		smbseterror(s, ERRDOS, ERRnofiles);
295
		pr = SmbProcessResultError;
296
		goto done;
297
	}
298
 
299
	if (search->t != t) {
300
		smbseterror(s, ERRSRV, ERRinvtid);
301
		pr = SmbProcessResultError;
302
		goto done;
303
	}
304
 
305
	if ((flags & (1 << 3)) == 0) {
306
		long i;
307
		if (filename == nil) {
308
			smbseterror(s, ERRDOS, ERRnofiles);
309
			pr = SmbProcessResultError;
310
			goto done;
311
		}
312
		for (i = 0; i < search->dc->n; i++)
313
			if (strcmp(search->dc->buf[i].name, filename) == 0) {
314
				search->dc->i = i + 1;
315
				break;
316
			}
317
	}
318
 
319
	populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset);
320
 
321
	eos = search->dc->i >= search->dc->n;
322
	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
323
		smbsearchclose(s, search);
324
	smbbufferputs(s->transaction.out.parameters, e);
325
	smbbufferputs(s->transaction.out.parameters, eos);
326
	smbbufferputs(s->transaction.out.parameters, 0);
327
	smbbufferputs(s->transaction.out.parameters, nameoffset);
328
	pr = SmbProcessResultReply;
329
done:
330
	smbbufferfree(&b);
331
	free(filename);
332
	return pr;
333
}